From b06de69f6acf6a1effa95c3303c18607bf861824 Mon Sep 17 00:00:00 2001 From: Margo Crawford Date: Thu, 1 Jul 2021 08:48:52 -0700 Subject: [PATCH] ActiveDirectoryIdentityProvider - Create CRD - Create implementation of AD-specific user search defaults --- apis/supervisor/idp/v1alpha1/register.go.tmpl | 4 +- ...es_activedirectoryidentityprovider.go.tmpl | 167 ++ .../idp/v1alpha1/types_meta.go.tmpl | 2 +- ....dev_activedirectoryidentityproviders.yaml | 271 ++++ generated/1.17/README.adoc | 153 ++ .../apis/supervisor/idp/v1alpha1/register.go | 4 +- .../types_activedirectoryidentityprovider.go | 167 ++ .../supervisor/idp/v1alpha1/types_meta.go | 2 +- .../idp/v1alpha1/zz_generated.deepcopy.go | 190 +++ .../activedirectoryidentityprovider.go | 178 +++ .../fake_activedirectoryidentityprovider.go | 127 ++ .../idp/v1alpha1/fake/fake_idp_client.go | 4 + .../typed/idp/v1alpha1/generated_expansion.go | 2 + .../typed/idp/v1alpha1/idp_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../activedirectoryidentityprovider.go | 76 + .../idp/v1alpha1/interface.go | 7 + .../activedirectoryidentityprovider.go | 81 + .../idp/v1alpha1/expansion_generated.go | 8 + ....dev_activedirectoryidentityproviders.yaml | 271 ++++ generated/1.18/README.adoc | 153 ++ .../apis/supervisor/idp/v1alpha1/register.go | 4 +- .../types_activedirectoryidentityprovider.go | 167 ++ .../supervisor/idp/v1alpha1/types_meta.go | 2 +- .../idp/v1alpha1/zz_generated.deepcopy.go | 190 +++ .../activedirectoryidentityprovider.go | 182 +++ .../fake_activedirectoryidentityprovider.go | 129 ++ .../idp/v1alpha1/fake/fake_idp_client.go | 4 + .../typed/idp/v1alpha1/generated_expansion.go | 2 + .../typed/idp/v1alpha1/idp_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../activedirectoryidentityprovider.go | 77 + .../idp/v1alpha1/interface.go | 7 + .../activedirectoryidentityprovider.go | 81 + .../idp/v1alpha1/expansion_generated.go | 8 + ....dev_activedirectoryidentityproviders.yaml | 271 ++++ generated/1.19/README.adoc | 153 ++ .../apis/supervisor/idp/v1alpha1/register.go | 4 +- .../types_activedirectoryidentityprovider.go | 167 ++ .../supervisor/idp/v1alpha1/types_meta.go | 2 +- .../idp/v1alpha1/zz_generated.deepcopy.go | 190 +++ .../activedirectoryidentityprovider.go | 182 +++ .../fake_activedirectoryidentityprovider.go | 129 ++ .../idp/v1alpha1/fake/fake_idp_client.go | 4 + .../typed/idp/v1alpha1/generated_expansion.go | 2 + .../typed/idp/v1alpha1/idp_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../activedirectoryidentityprovider.go | 77 + .../idp/v1alpha1/interface.go | 7 + .../activedirectoryidentityprovider.go | 86 ++ .../idp/v1alpha1/expansion_generated.go | 8 + ....dev_activedirectoryidentityproviders.yaml | 271 ++++ generated/1.20/README.adoc | 153 ++ .../apis/supervisor/idp/v1alpha1/register.go | 4 +- .../types_activedirectoryidentityprovider.go | 167 ++ .../supervisor/idp/v1alpha1/types_meta.go | 2 +- .../idp/v1alpha1/zz_generated.deepcopy.go | 190 +++ .../activedirectoryidentityprovider.go | 182 +++ .../fake_activedirectoryidentityprovider.go | 129 ++ .../idp/v1alpha1/fake/fake_idp_client.go | 4 + .../typed/idp/v1alpha1/generated_expansion.go | 2 + .../typed/idp/v1alpha1/idp_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../activedirectoryidentityprovider.go | 77 + .../idp/v1alpha1/interface.go | 7 + .../activedirectoryidentityprovider.go | 86 ++ .../idp/v1alpha1/expansion_generated.go | 8 + ....dev_activedirectoryidentityproviders.yaml | 271 ++++ .../apis/supervisor/idp/v1alpha1/register.go | 4 +- .../types_activedirectoryidentityprovider.go | 167 ++ .../supervisor/idp/v1alpha1/types_meta.go | 2 +- .../idp/v1alpha1/zz_generated.deepcopy.go | 190 +++ .../activedirectoryidentityprovider.go | 182 +++ .../fake_activedirectoryidentityprovider.go | 129 ++ .../idp/v1alpha1/fake/fake_idp_client.go | 4 + .../typed/idp/v1alpha1/generated_expansion.go | 2 + .../typed/idp/v1alpha1/idp_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../activedirectoryidentityprovider.go | 77 + .../idp/v1alpha1/interface.go | 7 + .../activedirectoryidentityprovider.go | 86 ++ .../idp/v1alpha1/expansion_generated.go | 8 + go.mod | 1 + go.sum | 1 + internal/upstreamad/upstreamad.go | 654 ++++++++ internal/upstreamad/upstreamad_test.go | 1375 +++++++++++++++++ 86 files changed, 8467 insertions(+), 12 deletions(-) create mode 100644 apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go.tmpl create mode 100644 deploy/supervisor/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml create mode 100644 generated/1.17/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go create mode 100644 generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go create mode 100644 generated/1.17/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.17/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.17/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml create mode 100644 generated/1.18/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go create mode 100644 generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go create mode 100644 generated/1.18/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.18/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.18/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml create mode 100644 generated/1.19/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go create mode 100644 generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go create mode 100644 generated/1.19/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.19/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.19/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml create mode 100644 generated/1.20/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go create mode 100644 generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go create mode 100644 generated/1.20/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.20/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/1.20/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml create mode 100644 generated/latest/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go create mode 100644 generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go create mode 100644 generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 generated/latest/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go create mode 100644 internal/upstreamad/upstreamad.go create mode 100644 internal/upstreamad/upstreamad_test.go diff --git a/apis/supervisor/idp/v1alpha1/register.go.tmpl b/apis/supervisor/idp/v1alpha1/register.go.tmpl index ddc9c360..e3406a81 100644 --- a/apis/supervisor/idp/v1alpha1/register.go.tmpl +++ b/apis/supervisor/idp/v1alpha1/register.go.tmpl @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 @@ -34,6 +34,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &OIDCIdentityProviderList{}, &LDAPIdentityProvider{}, &LDAPIdentityProviderList{}, + &ActiveDirectoryIdentityProvider{}, + &ActiveDirectoryIdentityProviderList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go.tmpl b/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go.tmpl new file mode 100644 index 00000000..18726e7b --- /dev/null +++ b/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go.tmpl @@ -0,0 +1,167 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ActiveDirectoryIdentityProviderPhase string + +const ( + // ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources. + ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending" + + // ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state. + ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready" + + // ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state. + ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error" +) + +// Status of an Active Directory identity provider. +type ActiveDirectoryIdentityProviderStatus struct { + // Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + // +kubebuilder:default=Pending + // +kubebuilder:validation:Enum=Pending;Ready;Error + Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"` + + // Represents the observations of an identity provider's current state. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +type ActiveDirectoryIdentityProviderBind struct { + // SecretName contains the name of a namespace-local Secret object that provides the username and + // password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be + // of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value + // should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + // The password must be non-empty. + // +kubebuilder:validation:MinLength=1 + SecretName string `json:"secretName"` +} + +type ActiveDirectoryIdentityProviderUserSearchAttributes struct { + // Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username + // of the user after a successful authentication. This would typically be the same attribute name used in + // Optional, when empty this defaults to "sAMAccountName". + // +optional + Username string `json:"username,omitempty"` + + // UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely + // identify the user within this ActiveDirectory provider after a successful authentication. + // Optional, when empty this defaults to "objectGUID". + // +optional + UID string `json:"uid,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearchAttributes struct { + // GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name + // in the user's list of groups after a successful authentication. + // The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory + // server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". + // Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). + // +optional + GroupName string `json:"groupName,omitempty"` +} + +type ActiveDirectoryIdentityProviderUserSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for users. + // E.g. "ou=users,dc=example,dc=com". + // Optional, when not specified it will be defaulted based on the host, for example if your active directory host is + // "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur + // in the filter at least once and will be dynamically replaced by the username for which the search is being run. + // E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as the value from + // Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be + // explicitly specified, since the default value of "dn={}" would not work. + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as + // the result of the user search. + // +optional + Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. + // "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and + // authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, + // the values of Filter and Attributes are ignored. + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. + // The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the + // dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or + // "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as "member={}". + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as + // the result of the group search. + // +optional + Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"` +} + +// Spec for configuring an ActiveDirectory identity provider. +type ActiveDirectoryIdentityProviderSpec struct { + // Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. + // +kubebuilder:validation:MinLength=1 + Host string `json:"host"` + + // TLS contains the connection settings for how to establish the connection to the Host. + TLS *TLSSpec `json:"tls,omitempty"` + + // Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server + // to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. + Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"` + + // UserSearch contains the configuration for searching for a user by name in Active Directory. + UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"` + + // GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. + GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"` +} + +// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps +// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host` +// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:subresource:status +type ActiveDirectoryIdentityProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec for configuring the identity provider. + Spec ActiveDirectoryIdentityProviderSpec `json:"spec"` + + // Status of the identity provider. + Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"` +} + +// List of ActiveDirectoryIdentityProvider objects. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ActiveDirectoryIdentityProviderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + Items []ActiveDirectoryIdentityProvider `json:"items"` +} diff --git a/apis/supervisor/idp/v1alpha1/types_meta.go.tmpl b/apis/supervisor/idp/v1alpha1/types_meta.go.tmpl index e59976ff..e04c6f2a 100644 --- a/apis/supervisor/idp/v1alpha1/types_meta.go.tmpl +++ b/apis/supervisor/idp/v1alpha1/types_meta.go.tmpl @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 diff --git a/deploy/supervisor/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml b/deploy/supervisor/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml new file mode 100644 index 00000000..03fbcd08 --- /dev/null +++ b/deploy/supervisor/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml @@ -0,0 +1,271 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev +spec: + group: idp.supervisor.pinniped.dev + names: + categories: + - pinniped + - pinniped-idp + - pinniped-idps + kind: ActiveDirectoryIdentityProvider + listKind: ActiveDirectoryIdentityProviderList + plural: activedirectoryidentityproviders + singular: activedirectoryidentityprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.host + name: Host + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ActiveDirectoryIdentityProvider describes the configuration of + an upstream Microsoft Active Directory identity provider. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec for configuring the identity provider. + properties: + bind: + description: Bind contains the configuration for how to provide access + credentials during an initial bind to the ActiveDirectory server + to be allowed to perform searches and binds to validate a user's + credentials during a user's authentication attempt. + properties: + secretName: + description: SecretName contains the name of a namespace-local + Secret object that provides the username and password for an + Active Directory bind user. This account will be used to perform + LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" + which includes "username" and "password" keys. The username + value should be the full dn (distinguished name) of your bind + account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + The password must be non-empty. + minLength: 1 + type: string + required: + - secretName + type: object + groupSearch: + description: GroupSearch contains the configuration for searching + for a user's group membership in ActiveDirectory. + properties: + attributes: + description: Attributes specifies how the group's information + should be read from each ActiveDirectory entry which was found + as the result of the group search. + properties: + groupName: + description: GroupName specifies the name of the attribute + in the Active Directory entries whose value shall become + a group name in the user's list of groups after a successful + authentication. The value of this field is case-sensitive + and must match the case of the attribute name returned by + the ActiveDirectory server in the user's entry. E.g. "cn" + for common name. Distinguished names can be used by specifying + lower-case "dn". Optional. When not specified, the default + will act as if the GroupName were specified as "dn" (distinguished + name). + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". + When not specified, no group search will be performed and authenticated + users will not belong to any groups from the ActiveDirectory + provider. Also, when not specified, the values of Filter and + Attributes are ignored. + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for groups for a user. The + pattern "{}" must occur in the filter at least once and will + be dynamically replaced by the dn (distinguished name) of the + user entry found as a result of the user search. E.g. "member={}" + or "&(objectClass=groupOfNames)(member={})". For more information + about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as "member={}". + type: string + type: object + host: + description: 'Host is the hostname of this Active Directory identity + provider, i.e., where to connect. For example: ldap.example.com:636.' + minLength: 1 + type: string + tls: + description: TLS contains the connection settings for how to establish + the connection to the Host. + properties: + certificateAuthorityData: + description: X.509 Certificate Authority (base64-encoded PEM bundle). + If omitted, a default set of system roots will be trusted. + type: string + type: object + userSearch: + description: UserSearch contains the configuration for searching for + a user by name in Active Directory. + properties: + attributes: + description: Attributes specifies how the user's information should + be read from the ActiveDirectory entry which was found as the + result of the user search. + properties: + uid: + description: UID specifies the name of the attribute in the + ActiveDirectory entry which whose value shall be used to + uniquely identify the user within this ActiveDirectory provider + after a successful authentication. Optional, when empty + this defaults to "objectGUID". + type: string + username: + description: Username specifies the name of the attribute + in the ActiveDirectory entry whose value shall become the + username of the user after a successful authentication. + This would typically be the same attribute name used in + Optional, when empty this defaults to "sAMAccountName". + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". + Optional, when not specified it will be defaulted based on the + host, for example if your active directory host is "activedirectory.example.com:636", + it will be "dc=activedirectory,dc=example,dc=com". + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for users. The pattern "{}" + must occur in the filter at least once and will be dynamically + replaced by the username for which the search is being run. + E.g. "mail={}" or "&(objectClass=person)(uid={})". For more + information about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as the + value from Attributes.Username appended by "={}". When the Attributes.Username + is set to "dn" then the Filter must be explicitly specified, + since the default value of "dn={}" would not work. + type: string + type: object + required: + - host + type: object + status: + description: Status of the identity provider. + properties: + conditions: + description: Represents the observations of an identity provider's + current state. + items: + description: Condition status of a resource (mirrored from the metav1.Condition + type added in Kubernetes 1.19). In a future API version we can + switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413. + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + phase: + default: Pending + description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + enum: + - Pending + - Ready + - Error + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/generated/1.17/README.adoc b/generated/1.17/README.adoc index cb311448..d0ba80df 100644 --- a/generated/1.17/README.adoc +++ b/generated/1.17/README.adoc @@ -748,6 +748,157 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro +[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider"] +==== ActiveDirectoryIdentityProvider + +ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderlist[$$ActiveDirectoryIdentityProviderList$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`. + +| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]__ | Spec for configuring the identity provider. +| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]__ | Status of the identity provider. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind"] +==== ActiveDirectoryIdentityProviderBind + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the username and password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password must be non-empty. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch"] +==== ActiveDirectoryIdentityProviderGroupSearch + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, the values of Filter and Attributes are ignored. +| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as "member={}". +| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes[$$ActiveDirectoryIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as the result of the group search. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes"] +==== ActiveDirectoryIdentityProviderGroupSearchAttributes + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`groupName`* __string__ | GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name in the user's list of groups after a successful authentication. The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). +|=== + + + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec"] +==== ActiveDirectoryIdentityProviderSpec + +Spec for configuring an ActiveDirectory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`host`* __string__ | Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. +| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-tlsspec[$$TLSSpec$$]__ | TLS contains the connection settings for how to establish the connection to the Host. +| *`bind`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind[$$ActiveDirectoryIdentityProviderBind$$]__ | Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. +| *`userSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$]__ | UserSearch contains the configuration for searching for a user by name in Active Directory. +| *`groupSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$]__ | GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus"] +==== ActiveDirectoryIdentityProviderStatus + +Status of an Active Directory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`phase`* __ActiveDirectoryIdentityProviderPhase__ | Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. +| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch"] +==== ActiveDirectoryIdentityProviderUserSearch + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". Optional, when not specified it will be defaulted based on the host, for example if your active directory host is "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". +| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the username for which the search is being run. E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as the value from Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be explicitly specified, since the default value of "dn={}" would not work. +| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes[$$ActiveDirectoryIdentityProviderUserSearchAttributes$$]__ | Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as the result of the user search. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes"] +==== ActiveDirectoryIdentityProviderUserSearchAttributes + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`username`* __string__ | Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username of the user after a successful authentication. This would typically be the same attribute name used in Optional, when empty this defaults to "sAMAccountName". +| *`uid`* __string__ | UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely identify the user within this ActiveDirectory provider after a successful authentication. Optional, when empty this defaults to "objectGUID". +|=== + + [id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-condition"] ==== Condition @@ -755,6 +906,7 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro .Appears In: **** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-oidcidentityproviderstatus[$$OIDCIdentityProviderStatus$$] **** @@ -1054,6 +1206,7 @@ Status of an OIDC identity provider. .Appears In: **** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-idp-v1alpha1-oidcidentityproviderspec[$$OIDCIdentityProviderSpec$$] **** diff --git a/generated/1.17/apis/supervisor/idp/v1alpha1/register.go b/generated/1.17/apis/supervisor/idp/v1alpha1/register.go index ddc9c360..e3406a81 100644 --- a/generated/1.17/apis/supervisor/idp/v1alpha1/register.go +++ b/generated/1.17/apis/supervisor/idp/v1alpha1/register.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 @@ -34,6 +34,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &OIDCIdentityProviderList{}, &LDAPIdentityProvider{}, &LDAPIdentityProviderList{}, + &ActiveDirectoryIdentityProvider{}, + &ActiveDirectoryIdentityProviderList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/generated/1.17/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go b/generated/1.17/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go new file mode 100644 index 00000000..18726e7b --- /dev/null +++ b/generated/1.17/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go @@ -0,0 +1,167 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ActiveDirectoryIdentityProviderPhase string + +const ( + // ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources. + ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending" + + // ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state. + ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready" + + // ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state. + ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error" +) + +// Status of an Active Directory identity provider. +type ActiveDirectoryIdentityProviderStatus struct { + // Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + // +kubebuilder:default=Pending + // +kubebuilder:validation:Enum=Pending;Ready;Error + Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"` + + // Represents the observations of an identity provider's current state. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +type ActiveDirectoryIdentityProviderBind struct { + // SecretName contains the name of a namespace-local Secret object that provides the username and + // password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be + // of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value + // should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + // The password must be non-empty. + // +kubebuilder:validation:MinLength=1 + SecretName string `json:"secretName"` +} + +type ActiveDirectoryIdentityProviderUserSearchAttributes struct { + // Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username + // of the user after a successful authentication. This would typically be the same attribute name used in + // Optional, when empty this defaults to "sAMAccountName". + // +optional + Username string `json:"username,omitempty"` + + // UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely + // identify the user within this ActiveDirectory provider after a successful authentication. + // Optional, when empty this defaults to "objectGUID". + // +optional + UID string `json:"uid,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearchAttributes struct { + // GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name + // in the user's list of groups after a successful authentication. + // The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory + // server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". + // Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). + // +optional + GroupName string `json:"groupName,omitempty"` +} + +type ActiveDirectoryIdentityProviderUserSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for users. + // E.g. "ou=users,dc=example,dc=com". + // Optional, when not specified it will be defaulted based on the host, for example if your active directory host is + // "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur + // in the filter at least once and will be dynamically replaced by the username for which the search is being run. + // E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as the value from + // Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be + // explicitly specified, since the default value of "dn={}" would not work. + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as + // the result of the user search. + // +optional + Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. + // "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and + // authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, + // the values of Filter and Attributes are ignored. + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. + // The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the + // dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or + // "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as "member={}". + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as + // the result of the group search. + // +optional + Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"` +} + +// Spec for configuring an ActiveDirectory identity provider. +type ActiveDirectoryIdentityProviderSpec struct { + // Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. + // +kubebuilder:validation:MinLength=1 + Host string `json:"host"` + + // TLS contains the connection settings for how to establish the connection to the Host. + TLS *TLSSpec `json:"tls,omitempty"` + + // Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server + // to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. + Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"` + + // UserSearch contains the configuration for searching for a user by name in Active Directory. + UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"` + + // GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. + GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"` +} + +// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps +// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host` +// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:subresource:status +type ActiveDirectoryIdentityProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec for configuring the identity provider. + Spec ActiveDirectoryIdentityProviderSpec `json:"spec"` + + // Status of the identity provider. + Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"` +} + +// List of ActiveDirectoryIdentityProvider objects. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ActiveDirectoryIdentityProviderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + Items []ActiveDirectoryIdentityProvider `json:"items"` +} diff --git a/generated/1.17/apis/supervisor/idp/v1alpha1/types_meta.go b/generated/1.17/apis/supervisor/idp/v1alpha1/types_meta.go index e59976ff..e04c6f2a 100644 --- a/generated/1.17/apis/supervisor/idp/v1alpha1/types_meta.go +++ b/generated/1.17/apis/supervisor/idp/v1alpha1/types_meta.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 diff --git a/generated/1.17/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go b/generated/1.17/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go index f7762b09..9895a76e 100644 --- a/generated/1.17/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.17/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go @@ -11,6 +11,196 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProvider) DeepCopyInto(out *ActiveDirectoryIdentityProvider) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProvider. +func (in *ActiveDirectoryIdentityProvider) DeepCopy() *ActiveDirectoryIdentityProvider { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProvider) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopyInto(out *ActiveDirectoryIdentityProviderBind) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderBind. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopy() *ActiveDirectoryIdentityProviderBind { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderBind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearch. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearchAttributes. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearchAttributes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyInto(out *ActiveDirectoryIdentityProviderList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ActiveDirectoryIdentityProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderList. +func (in *ActiveDirectoryIdentityProviderList) DeepCopy() *ActiveDirectoryIdentityProviderList { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopyInto(out *ActiveDirectoryIdentityProviderSpec) { + *out = *in + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLSSpec) + **out = **in + } + out.Bind = in.Bind + out.UserSearch = in.UserSearch + out.GroupSearch = in.GroupSearch + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderSpec. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopy() *ActiveDirectoryIdentityProviderSpec { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopyInto(out *ActiveDirectoryIdentityProviderStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderStatus. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopy() *ActiveDirectoryIdentityProviderStatus { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearch. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopy() *ActiveDirectoryIdentityProviderUserSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearchAttributes. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderUserSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearchAttributes) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Condition) DeepCopyInto(out *Condition) { *out = *in diff --git a/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..bfcd3c10 --- /dev/null +++ b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,178 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1" + scheme "go.pinniped.dev/generated/1.17/client/supervisor/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ActiveDirectoryIdentityProvidersGetter has a method to return a ActiveDirectoryIdentityProviderInterface. +// A group's client should implement this interface. +type ActiveDirectoryIdentityProvidersGetter interface { + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface +} + +// ActiveDirectoryIdentityProviderInterface has methods to work with ActiveDirectoryIdentityProvider resources. +type ActiveDirectoryIdentityProviderInterface interface { + Create(*v1alpha1.ActiveDirectoryIdentityProvider) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Update(*v1alpha1.ActiveDirectoryIdentityProvider) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + UpdateStatus(*v1alpha1.ActiveDirectoryIdentityProvider) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + List(opts v1.ListOptions) (*v1alpha1.ActiveDirectoryIdentityProviderList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) + ActiveDirectoryIdentityProviderExpansion +} + +// activeDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type activeDirectoryIdentityProviders struct { + client rest.Interface + ns string +} + +// newActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviders +func newActiveDirectoryIdentityProviders(c *IDPV1alpha1Client, namespace string) *activeDirectoryIdentityProviders { + return &activeDirectoryIdentityProviders{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *activeDirectoryIdentityProviders) Get(name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *activeDirectoryIdentityProviders) List(opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ActiveDirectoryIdentityProviderList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *activeDirectoryIdentityProviders) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Create(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Post(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Body(activeDirectoryIdentityProvider). + Do(). + Into(result) + return +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Update(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + Body(activeDirectoryIdentityProvider). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *activeDirectoryIdentityProviders) UpdateStatus(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + SubResource("status"). + Body(activeDirectoryIdentityProvider). + Do(). + Into(result) + return +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *activeDirectoryIdentityProviders) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *activeDirectoryIdentityProviders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *activeDirectoryIdentityProviders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go new file mode 100644 index 00000000..0b3842a0 --- /dev/null +++ b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go @@ -0,0 +1,127 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeActiveDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type FakeActiveDirectoryIdentityProviders struct { + Fake *FakeIDPV1alpha1 + ns string +} + +var activedirectoryidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "activedirectoryidentityproviders"} + +var activedirectoryidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "ActiveDirectoryIdentityProvider"} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Get(name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *FakeActiveDirectoryIdentityProviders) List(opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(activedirectoryidentityprovidersResource, activedirectoryidentityprovidersKind, c.ns, opts), &v1alpha1.ActiveDirectoryIdentityProviderList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ActiveDirectoryIdentityProviderList{ListMeta: obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).ListMeta} + for _, item := range obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *FakeActiveDirectoryIdentityProviders) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(activedirectoryidentityprovidersResource, c.ns, opts)) + +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Create(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Update(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeActiveDirectoryIdentityProviders) UpdateStatus(activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(activedirectoryidentityprovidersResource, "status", c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *FakeActiveDirectoryIdentityProviders) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeActiveDirectoryIdentityProviders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(activedirectoryidentityprovidersResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.ActiveDirectoryIdentityProviderList{}) + return err +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *FakeActiveDirectoryIdentityProviders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(activedirectoryidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} diff --git a/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go index 23859d83..4879c13e 100644 --- a/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go +++ b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go @@ -15,6 +15,10 @@ type FakeIDPV1alpha1 struct { *testing.Fake } +func (c *FakeIDPV1alpha1) ActiveDirectoryIdentityProviders(namespace string) v1alpha1.ActiveDirectoryIdentityProviderInterface { + return &FakeActiveDirectoryIdentityProviders{c, namespace} +} + func (c *FakeIDPV1alpha1) LDAPIdentityProviders(namespace string) v1alpha1.LDAPIdentityProviderInterface { return &FakeLDAPIdentityProviders{c, namespace} } diff --git a/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go index 137892f3..a7fdb511 100644 --- a/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go +++ b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go @@ -5,6 +5,8 @@ package v1alpha1 +type ActiveDirectoryIdentityProviderExpansion interface{} + type LDAPIdentityProviderExpansion interface{} type OIDCIdentityProviderExpansion interface{} diff --git a/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go index 9176e752..bcae95d9 100644 --- a/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go +++ b/generated/1.17/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go @@ -13,6 +13,7 @@ import ( type IDPV1alpha1Interface interface { RESTClient() rest.Interface + ActiveDirectoryIdentityProvidersGetter LDAPIdentityProvidersGetter OIDCIdentityProvidersGetter } @@ -22,6 +23,10 @@ type IDPV1alpha1Client struct { restClient rest.Interface } +func (c *IDPV1alpha1Client) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface { + return newActiveDirectoryIdentityProviders(c, namespace) +} + func (c *IDPV1alpha1Client) LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface { return newLDAPIdentityProviders(c, namespace) } diff --git a/generated/1.17/client/supervisor/informers/externalversions/generic.go b/generated/1.17/client/supervisor/informers/externalversions/generic.go index f65c952d..b3f29c6a 100644 --- a/generated/1.17/client/supervisor/informers/externalversions/generic.go +++ b/generated/1.17/client/supervisor/informers/externalversions/generic.go @@ -45,6 +45,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().FederationDomains().Informer()}, nil // Group=idp.supervisor.pinniped.dev, Version=v1alpha1 + case idpv1alpha1.SchemeGroupVersion.WithResource("activedirectoryidentityproviders"): + return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().ActiveDirectoryIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("ldapidentityproviders"): return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().LDAPIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("oidcidentityproviders"): diff --git a/generated/1.17/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.17/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..4757c8ae --- /dev/null +++ b/generated/1.17/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,76 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + idpv1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1" + versioned "go.pinniped.dev/generated/1.17/client/supervisor/clientset/versioned" + internalinterfaces "go.pinniped.dev/generated/1.17/client/supervisor/informers/externalversions/internalinterfaces" + v1alpha1 "go.pinniped.dev/generated/1.17/client/supervisor/listers/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderInformer provides access to a shared informer and lister for +// ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ActiveDirectoryIdentityProviderLister +} + +type activeDirectoryIdentityProviderInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).Watch(options) + }, + }, + &idpv1alpha1.ActiveDirectoryIdentityProvider{}, + resyncPeriod, + indexers, + ) +} + +func (f *activeDirectoryIdentityProviderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *activeDirectoryIdentityProviderInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&idpv1alpha1.ActiveDirectoryIdentityProvider{}, f.defaultInformer) +} + +func (f *activeDirectoryIdentityProviderInformer) Lister() v1alpha1.ActiveDirectoryIdentityProviderLister { + return v1alpha1.NewActiveDirectoryIdentityProviderLister(f.Informer().GetIndexer()) +} diff --git a/generated/1.17/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go b/generated/1.17/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go index b7677ddb..4e29527e 100644 --- a/generated/1.17/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go +++ b/generated/1.17/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go @@ -11,6 +11,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. + ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. LDAPIdentityProviders() LDAPIdentityProviderInformer // OIDCIdentityProviders returns a OIDCIdentityProviderInformer. @@ -28,6 +30,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. +func (v *version) ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer { + return &activeDirectoryIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. func (v *version) LDAPIdentityProviders() LDAPIdentityProviderInformer { return &lDAPIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/generated/1.17/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.17/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..7dbde172 --- /dev/null +++ b/generated/1.17/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,81 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "go.pinniped.dev/generated/1.17/apis/supervisor/idp/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderLister helps list ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister + ActiveDirectoryIdentityProviderListerExpansion +} + +// activeDirectoryIdentityProviderLister implements the ActiveDirectoryIdentityProviderLister interface. +type activeDirectoryIdentityProviderLister struct { + indexer cache.Indexer +} + +// NewActiveDirectoryIdentityProviderLister returns a new ActiveDirectoryIdentityProviderLister. +func NewActiveDirectoryIdentityProviderLister(indexer cache.Indexer) ActiveDirectoryIdentityProviderLister { + return &activeDirectoryIdentityProviderLister{indexer: indexer} +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer. +func (s *activeDirectoryIdentityProviderLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. +func (s *activeDirectoryIdentityProviderLister) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister { + return activeDirectoryIdentityProviderNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ActiveDirectoryIdentityProviderNamespaceLister helps list and get ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderNamespaceLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + ActiveDirectoryIdentityProviderNamespaceListerExpansion +} + +// activeDirectoryIdentityProviderNamespaceLister implements the ActiveDirectoryIdentityProviderNamespaceLister +// interface. +type activeDirectoryIdentityProviderNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. +func (s activeDirectoryIdentityProviderNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. +func (s activeDirectoryIdentityProviderNamespaceLister) Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("activedirectoryidentityprovider"), name) + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), nil +} diff --git a/generated/1.17/client/supervisor/listers/idp/v1alpha1/expansion_generated.go b/generated/1.17/client/supervisor/listers/idp/v1alpha1/expansion_generated.go index 28f41bd7..7c625e80 100644 --- a/generated/1.17/client/supervisor/listers/idp/v1alpha1/expansion_generated.go +++ b/generated/1.17/client/supervisor/listers/idp/v1alpha1/expansion_generated.go @@ -5,6 +5,14 @@ package v1alpha1 +// ActiveDirectoryIdentityProviderListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderLister. +type ActiveDirectoryIdentityProviderListerExpansion interface{} + +// ActiveDirectoryIdentityProviderNamespaceListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderNamespaceLister. +type ActiveDirectoryIdentityProviderNamespaceListerExpansion interface{} + // LDAPIdentityProviderListerExpansion allows custom methods to be added to // LDAPIdentityProviderLister. type LDAPIdentityProviderListerExpansion interface{} diff --git a/generated/1.17/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml b/generated/1.17/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml new file mode 100644 index 00000000..03fbcd08 --- /dev/null +++ b/generated/1.17/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml @@ -0,0 +1,271 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev +spec: + group: idp.supervisor.pinniped.dev + names: + categories: + - pinniped + - pinniped-idp + - pinniped-idps + kind: ActiveDirectoryIdentityProvider + listKind: ActiveDirectoryIdentityProviderList + plural: activedirectoryidentityproviders + singular: activedirectoryidentityprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.host + name: Host + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ActiveDirectoryIdentityProvider describes the configuration of + an upstream Microsoft Active Directory identity provider. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec for configuring the identity provider. + properties: + bind: + description: Bind contains the configuration for how to provide access + credentials during an initial bind to the ActiveDirectory server + to be allowed to perform searches and binds to validate a user's + credentials during a user's authentication attempt. + properties: + secretName: + description: SecretName contains the name of a namespace-local + Secret object that provides the username and password for an + Active Directory bind user. This account will be used to perform + LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" + which includes "username" and "password" keys. The username + value should be the full dn (distinguished name) of your bind + account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + The password must be non-empty. + minLength: 1 + type: string + required: + - secretName + type: object + groupSearch: + description: GroupSearch contains the configuration for searching + for a user's group membership in ActiveDirectory. + properties: + attributes: + description: Attributes specifies how the group's information + should be read from each ActiveDirectory entry which was found + as the result of the group search. + properties: + groupName: + description: GroupName specifies the name of the attribute + in the Active Directory entries whose value shall become + a group name in the user's list of groups after a successful + authentication. The value of this field is case-sensitive + and must match the case of the attribute name returned by + the ActiveDirectory server in the user's entry. E.g. "cn" + for common name. Distinguished names can be used by specifying + lower-case "dn". Optional. When not specified, the default + will act as if the GroupName were specified as "dn" (distinguished + name). + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". + When not specified, no group search will be performed and authenticated + users will not belong to any groups from the ActiveDirectory + provider. Also, when not specified, the values of Filter and + Attributes are ignored. + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for groups for a user. The + pattern "{}" must occur in the filter at least once and will + be dynamically replaced by the dn (distinguished name) of the + user entry found as a result of the user search. E.g. "member={}" + or "&(objectClass=groupOfNames)(member={})". For more information + about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as "member={}". + type: string + type: object + host: + description: 'Host is the hostname of this Active Directory identity + provider, i.e., where to connect. For example: ldap.example.com:636.' + minLength: 1 + type: string + tls: + description: TLS contains the connection settings for how to establish + the connection to the Host. + properties: + certificateAuthorityData: + description: X.509 Certificate Authority (base64-encoded PEM bundle). + If omitted, a default set of system roots will be trusted. + type: string + type: object + userSearch: + description: UserSearch contains the configuration for searching for + a user by name in Active Directory. + properties: + attributes: + description: Attributes specifies how the user's information should + be read from the ActiveDirectory entry which was found as the + result of the user search. + properties: + uid: + description: UID specifies the name of the attribute in the + ActiveDirectory entry which whose value shall be used to + uniquely identify the user within this ActiveDirectory provider + after a successful authentication. Optional, when empty + this defaults to "objectGUID". + type: string + username: + description: Username specifies the name of the attribute + in the ActiveDirectory entry whose value shall become the + username of the user after a successful authentication. + This would typically be the same attribute name used in + Optional, when empty this defaults to "sAMAccountName". + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". + Optional, when not specified it will be defaulted based on the + host, for example if your active directory host is "activedirectory.example.com:636", + it will be "dc=activedirectory,dc=example,dc=com". + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for users. The pattern "{}" + must occur in the filter at least once and will be dynamically + replaced by the username for which the search is being run. + E.g. "mail={}" or "&(objectClass=person)(uid={})". For more + information about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as the + value from Attributes.Username appended by "={}". When the Attributes.Username + is set to "dn" then the Filter must be explicitly specified, + since the default value of "dn={}" would not work. + type: string + type: object + required: + - host + type: object + status: + description: Status of the identity provider. + properties: + conditions: + description: Represents the observations of an identity provider's + current state. + items: + description: Condition status of a resource (mirrored from the metav1.Condition + type added in Kubernetes 1.19). In a future API version we can + switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413. + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + phase: + default: Pending + description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + enum: + - Pending + - Ready + - Error + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/generated/1.18/README.adoc b/generated/1.18/README.adoc index ade6ea1b..12946f74 100644 --- a/generated/1.18/README.adoc +++ b/generated/1.18/README.adoc @@ -748,6 +748,157 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro +[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider"] +==== ActiveDirectoryIdentityProvider + +ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderlist[$$ActiveDirectoryIdentityProviderList$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`. + +| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]__ | Spec for configuring the identity provider. +| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]__ | Status of the identity provider. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind"] +==== ActiveDirectoryIdentityProviderBind + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the username and password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password must be non-empty. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch"] +==== ActiveDirectoryIdentityProviderGroupSearch + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, the values of Filter and Attributes are ignored. +| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as "member={}". +| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes[$$ActiveDirectoryIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as the result of the group search. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes"] +==== ActiveDirectoryIdentityProviderGroupSearchAttributes + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`groupName`* __string__ | GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name in the user's list of groups after a successful authentication. The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). +|=== + + + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec"] +==== ActiveDirectoryIdentityProviderSpec + +Spec for configuring an ActiveDirectory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`host`* __string__ | Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. +| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-tlsspec[$$TLSSpec$$]__ | TLS contains the connection settings for how to establish the connection to the Host. +| *`bind`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind[$$ActiveDirectoryIdentityProviderBind$$]__ | Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. +| *`userSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$]__ | UserSearch contains the configuration for searching for a user by name in Active Directory. +| *`groupSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$]__ | GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus"] +==== ActiveDirectoryIdentityProviderStatus + +Status of an Active Directory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`phase`* __ActiveDirectoryIdentityProviderPhase__ | Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. +| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch"] +==== ActiveDirectoryIdentityProviderUserSearch + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". Optional, when not specified it will be defaulted based on the host, for example if your active directory host is "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". +| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the username for which the search is being run. E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as the value from Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be explicitly specified, since the default value of "dn={}" would not work. +| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes[$$ActiveDirectoryIdentityProviderUserSearchAttributes$$]__ | Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as the result of the user search. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes"] +==== ActiveDirectoryIdentityProviderUserSearchAttributes + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`username`* __string__ | Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username of the user after a successful authentication. This would typically be the same attribute name used in Optional, when empty this defaults to "sAMAccountName". +| *`uid`* __string__ | UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely identify the user within this ActiveDirectory provider after a successful authentication. Optional, when empty this defaults to "objectGUID". +|=== + + [id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-condition"] ==== Condition @@ -755,6 +906,7 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro .Appears In: **** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-oidcidentityproviderstatus[$$OIDCIdentityProviderStatus$$] **** @@ -1054,6 +1206,7 @@ Status of an OIDC identity provider. .Appears In: **** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-idp-v1alpha1-oidcidentityproviderspec[$$OIDCIdentityProviderSpec$$] **** diff --git a/generated/1.18/apis/supervisor/idp/v1alpha1/register.go b/generated/1.18/apis/supervisor/idp/v1alpha1/register.go index ddc9c360..e3406a81 100644 --- a/generated/1.18/apis/supervisor/idp/v1alpha1/register.go +++ b/generated/1.18/apis/supervisor/idp/v1alpha1/register.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 @@ -34,6 +34,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &OIDCIdentityProviderList{}, &LDAPIdentityProvider{}, &LDAPIdentityProviderList{}, + &ActiveDirectoryIdentityProvider{}, + &ActiveDirectoryIdentityProviderList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/generated/1.18/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go b/generated/1.18/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go new file mode 100644 index 00000000..18726e7b --- /dev/null +++ b/generated/1.18/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go @@ -0,0 +1,167 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ActiveDirectoryIdentityProviderPhase string + +const ( + // ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources. + ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending" + + // ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state. + ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready" + + // ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state. + ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error" +) + +// Status of an Active Directory identity provider. +type ActiveDirectoryIdentityProviderStatus struct { + // Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + // +kubebuilder:default=Pending + // +kubebuilder:validation:Enum=Pending;Ready;Error + Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"` + + // Represents the observations of an identity provider's current state. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +type ActiveDirectoryIdentityProviderBind struct { + // SecretName contains the name of a namespace-local Secret object that provides the username and + // password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be + // of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value + // should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + // The password must be non-empty. + // +kubebuilder:validation:MinLength=1 + SecretName string `json:"secretName"` +} + +type ActiveDirectoryIdentityProviderUserSearchAttributes struct { + // Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username + // of the user after a successful authentication. This would typically be the same attribute name used in + // Optional, when empty this defaults to "sAMAccountName". + // +optional + Username string `json:"username,omitempty"` + + // UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely + // identify the user within this ActiveDirectory provider after a successful authentication. + // Optional, when empty this defaults to "objectGUID". + // +optional + UID string `json:"uid,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearchAttributes struct { + // GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name + // in the user's list of groups after a successful authentication. + // The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory + // server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". + // Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). + // +optional + GroupName string `json:"groupName,omitempty"` +} + +type ActiveDirectoryIdentityProviderUserSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for users. + // E.g. "ou=users,dc=example,dc=com". + // Optional, when not specified it will be defaulted based on the host, for example if your active directory host is + // "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur + // in the filter at least once and will be dynamically replaced by the username for which the search is being run. + // E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as the value from + // Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be + // explicitly specified, since the default value of "dn={}" would not work. + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as + // the result of the user search. + // +optional + Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. + // "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and + // authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, + // the values of Filter and Attributes are ignored. + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. + // The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the + // dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or + // "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as "member={}". + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as + // the result of the group search. + // +optional + Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"` +} + +// Spec for configuring an ActiveDirectory identity provider. +type ActiveDirectoryIdentityProviderSpec struct { + // Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. + // +kubebuilder:validation:MinLength=1 + Host string `json:"host"` + + // TLS contains the connection settings for how to establish the connection to the Host. + TLS *TLSSpec `json:"tls,omitempty"` + + // Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server + // to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. + Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"` + + // UserSearch contains the configuration for searching for a user by name in Active Directory. + UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"` + + // GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. + GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"` +} + +// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps +// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host` +// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:subresource:status +type ActiveDirectoryIdentityProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec for configuring the identity provider. + Spec ActiveDirectoryIdentityProviderSpec `json:"spec"` + + // Status of the identity provider. + Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"` +} + +// List of ActiveDirectoryIdentityProvider objects. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ActiveDirectoryIdentityProviderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + Items []ActiveDirectoryIdentityProvider `json:"items"` +} diff --git a/generated/1.18/apis/supervisor/idp/v1alpha1/types_meta.go b/generated/1.18/apis/supervisor/idp/v1alpha1/types_meta.go index e59976ff..e04c6f2a 100644 --- a/generated/1.18/apis/supervisor/idp/v1alpha1/types_meta.go +++ b/generated/1.18/apis/supervisor/idp/v1alpha1/types_meta.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 diff --git a/generated/1.18/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go b/generated/1.18/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go index f7762b09..9895a76e 100644 --- a/generated/1.18/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.18/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go @@ -11,6 +11,196 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProvider) DeepCopyInto(out *ActiveDirectoryIdentityProvider) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProvider. +func (in *ActiveDirectoryIdentityProvider) DeepCopy() *ActiveDirectoryIdentityProvider { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProvider) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopyInto(out *ActiveDirectoryIdentityProviderBind) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderBind. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopy() *ActiveDirectoryIdentityProviderBind { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderBind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearch. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearchAttributes. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearchAttributes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyInto(out *ActiveDirectoryIdentityProviderList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ActiveDirectoryIdentityProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderList. +func (in *ActiveDirectoryIdentityProviderList) DeepCopy() *ActiveDirectoryIdentityProviderList { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopyInto(out *ActiveDirectoryIdentityProviderSpec) { + *out = *in + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLSSpec) + **out = **in + } + out.Bind = in.Bind + out.UserSearch = in.UserSearch + out.GroupSearch = in.GroupSearch + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderSpec. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopy() *ActiveDirectoryIdentityProviderSpec { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopyInto(out *ActiveDirectoryIdentityProviderStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderStatus. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopy() *ActiveDirectoryIdentityProviderStatus { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearch. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopy() *ActiveDirectoryIdentityProviderUserSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearchAttributes. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderUserSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearchAttributes) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Condition) DeepCopyInto(out *Condition) { *out = *in diff --git a/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..5d2cd3ca --- /dev/null +++ b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,182 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1" + scheme "go.pinniped.dev/generated/1.18/client/supervisor/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ActiveDirectoryIdentityProvidersGetter has a method to return a ActiveDirectoryIdentityProviderInterface. +// A group's client should implement this interface. +type ActiveDirectoryIdentityProvidersGetter interface { + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface +} + +// ActiveDirectoryIdentityProviderInterface has methods to work with ActiveDirectoryIdentityProvider resources. +type ActiveDirectoryIdentityProviderInterface interface { + Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ActiveDirectoryIdentityProviderList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) + ActiveDirectoryIdentityProviderExpansion +} + +// activeDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type activeDirectoryIdentityProviders struct { + client rest.Interface + ns string +} + +// newActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviders +func newActiveDirectoryIdentityProviders(c *IDPV1alpha1Client, namespace string) *activeDirectoryIdentityProviders { + return &activeDirectoryIdentityProviders{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *activeDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *activeDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ActiveDirectoryIdentityProviderList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *activeDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Post(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *activeDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *activeDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *activeDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *activeDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go new file mode 100644 index 00000000..d3f12004 --- /dev/null +++ b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go @@ -0,0 +1,129 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeActiveDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type FakeActiveDirectoryIdentityProviders struct { + Fake *FakeIDPV1alpha1 + ns string +} + +var activedirectoryidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "activedirectoryidentityproviders"} + +var activedirectoryidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "ActiveDirectoryIdentityProvider"} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *FakeActiveDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(activedirectoryidentityprovidersResource, activedirectoryidentityprovidersKind, c.ns, opts), &v1alpha1.ActiveDirectoryIdentityProviderList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ActiveDirectoryIdentityProviderList{ListMeta: obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).ListMeta} + for _, item := range obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *FakeActiveDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(activedirectoryidentityprovidersResource, c.ns, opts)) + +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeActiveDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(activedirectoryidentityprovidersResource, "status", c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *FakeActiveDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeActiveDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(activedirectoryidentityprovidersResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ActiveDirectoryIdentityProviderList{}) + return err +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *FakeActiveDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(activedirectoryidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} diff --git a/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go index 2c419ceb..669a43cb 100644 --- a/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go +++ b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go @@ -15,6 +15,10 @@ type FakeIDPV1alpha1 struct { *testing.Fake } +func (c *FakeIDPV1alpha1) ActiveDirectoryIdentityProviders(namespace string) v1alpha1.ActiveDirectoryIdentityProviderInterface { + return &FakeActiveDirectoryIdentityProviders{c, namespace} +} + func (c *FakeIDPV1alpha1) LDAPIdentityProviders(namespace string) v1alpha1.LDAPIdentityProviderInterface { return &FakeLDAPIdentityProviders{c, namespace} } diff --git a/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go index 137892f3..a7fdb511 100644 --- a/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go +++ b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go @@ -5,6 +5,8 @@ package v1alpha1 +type ActiveDirectoryIdentityProviderExpansion interface{} + type LDAPIdentityProviderExpansion interface{} type OIDCIdentityProviderExpansion interface{} diff --git a/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go index fdb10351..208b4543 100644 --- a/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go +++ b/generated/1.18/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go @@ -13,6 +13,7 @@ import ( type IDPV1alpha1Interface interface { RESTClient() rest.Interface + ActiveDirectoryIdentityProvidersGetter LDAPIdentityProvidersGetter OIDCIdentityProvidersGetter } @@ -22,6 +23,10 @@ type IDPV1alpha1Client struct { restClient rest.Interface } +func (c *IDPV1alpha1Client) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface { + return newActiveDirectoryIdentityProviders(c, namespace) +} + func (c *IDPV1alpha1Client) LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface { return newLDAPIdentityProviders(c, namespace) } diff --git a/generated/1.18/client/supervisor/informers/externalversions/generic.go b/generated/1.18/client/supervisor/informers/externalversions/generic.go index 9d15fcd2..9a2e9853 100644 --- a/generated/1.18/client/supervisor/informers/externalversions/generic.go +++ b/generated/1.18/client/supervisor/informers/externalversions/generic.go @@ -45,6 +45,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().FederationDomains().Informer()}, nil // Group=idp.supervisor.pinniped.dev, Version=v1alpha1 + case idpv1alpha1.SchemeGroupVersion.WithResource("activedirectoryidentityproviders"): + return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().ActiveDirectoryIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("ldapidentityproviders"): return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().LDAPIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("oidcidentityproviders"): diff --git a/generated/1.18/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.18/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..54647c94 --- /dev/null +++ b/generated/1.18/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,77 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + idpv1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1" + versioned "go.pinniped.dev/generated/1.18/client/supervisor/clientset/versioned" + internalinterfaces "go.pinniped.dev/generated/1.18/client/supervisor/informers/externalversions/internalinterfaces" + v1alpha1 "go.pinniped.dev/generated/1.18/client/supervisor/listers/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderInformer provides access to a shared informer and lister for +// ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ActiveDirectoryIdentityProviderLister +} + +type activeDirectoryIdentityProviderInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).Watch(context.TODO(), options) + }, + }, + &idpv1alpha1.ActiveDirectoryIdentityProvider{}, + resyncPeriod, + indexers, + ) +} + +func (f *activeDirectoryIdentityProviderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *activeDirectoryIdentityProviderInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&idpv1alpha1.ActiveDirectoryIdentityProvider{}, f.defaultInformer) +} + +func (f *activeDirectoryIdentityProviderInformer) Lister() v1alpha1.ActiveDirectoryIdentityProviderLister { + return v1alpha1.NewActiveDirectoryIdentityProviderLister(f.Informer().GetIndexer()) +} diff --git a/generated/1.18/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go b/generated/1.18/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go index 009ad89c..9456d5e2 100644 --- a/generated/1.18/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go +++ b/generated/1.18/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go @@ -11,6 +11,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. + ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. LDAPIdentityProviders() LDAPIdentityProviderInformer // OIDCIdentityProviders returns a OIDCIdentityProviderInformer. @@ -28,6 +30,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. +func (v *version) ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer { + return &activeDirectoryIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. func (v *version) LDAPIdentityProviders() LDAPIdentityProviderInformer { return &lDAPIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/generated/1.18/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.18/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..91025764 --- /dev/null +++ b/generated/1.18/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,81 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "go.pinniped.dev/generated/1.18/apis/supervisor/idp/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderLister helps list ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister + ActiveDirectoryIdentityProviderListerExpansion +} + +// activeDirectoryIdentityProviderLister implements the ActiveDirectoryIdentityProviderLister interface. +type activeDirectoryIdentityProviderLister struct { + indexer cache.Indexer +} + +// NewActiveDirectoryIdentityProviderLister returns a new ActiveDirectoryIdentityProviderLister. +func NewActiveDirectoryIdentityProviderLister(indexer cache.Indexer) ActiveDirectoryIdentityProviderLister { + return &activeDirectoryIdentityProviderLister{indexer: indexer} +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer. +func (s *activeDirectoryIdentityProviderLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. +func (s *activeDirectoryIdentityProviderLister) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister { + return activeDirectoryIdentityProviderNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ActiveDirectoryIdentityProviderNamespaceLister helps list and get ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderNamespaceLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + ActiveDirectoryIdentityProviderNamespaceListerExpansion +} + +// activeDirectoryIdentityProviderNamespaceLister implements the ActiveDirectoryIdentityProviderNamespaceLister +// interface. +type activeDirectoryIdentityProviderNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. +func (s activeDirectoryIdentityProviderNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. +func (s activeDirectoryIdentityProviderNamespaceLister) Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("activedirectoryidentityprovider"), name) + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), nil +} diff --git a/generated/1.18/client/supervisor/listers/idp/v1alpha1/expansion_generated.go b/generated/1.18/client/supervisor/listers/idp/v1alpha1/expansion_generated.go index 28f41bd7..7c625e80 100644 --- a/generated/1.18/client/supervisor/listers/idp/v1alpha1/expansion_generated.go +++ b/generated/1.18/client/supervisor/listers/idp/v1alpha1/expansion_generated.go @@ -5,6 +5,14 @@ package v1alpha1 +// ActiveDirectoryIdentityProviderListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderLister. +type ActiveDirectoryIdentityProviderListerExpansion interface{} + +// ActiveDirectoryIdentityProviderNamespaceListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderNamespaceLister. +type ActiveDirectoryIdentityProviderNamespaceListerExpansion interface{} + // LDAPIdentityProviderListerExpansion allows custom methods to be added to // LDAPIdentityProviderLister. type LDAPIdentityProviderListerExpansion interface{} diff --git a/generated/1.18/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml b/generated/1.18/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml new file mode 100644 index 00000000..03fbcd08 --- /dev/null +++ b/generated/1.18/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml @@ -0,0 +1,271 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev +spec: + group: idp.supervisor.pinniped.dev + names: + categories: + - pinniped + - pinniped-idp + - pinniped-idps + kind: ActiveDirectoryIdentityProvider + listKind: ActiveDirectoryIdentityProviderList + plural: activedirectoryidentityproviders + singular: activedirectoryidentityprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.host + name: Host + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ActiveDirectoryIdentityProvider describes the configuration of + an upstream Microsoft Active Directory identity provider. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec for configuring the identity provider. + properties: + bind: + description: Bind contains the configuration for how to provide access + credentials during an initial bind to the ActiveDirectory server + to be allowed to perform searches and binds to validate a user's + credentials during a user's authentication attempt. + properties: + secretName: + description: SecretName contains the name of a namespace-local + Secret object that provides the username and password for an + Active Directory bind user. This account will be used to perform + LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" + which includes "username" and "password" keys. The username + value should be the full dn (distinguished name) of your bind + account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + The password must be non-empty. + minLength: 1 + type: string + required: + - secretName + type: object + groupSearch: + description: GroupSearch contains the configuration for searching + for a user's group membership in ActiveDirectory. + properties: + attributes: + description: Attributes specifies how the group's information + should be read from each ActiveDirectory entry which was found + as the result of the group search. + properties: + groupName: + description: GroupName specifies the name of the attribute + in the Active Directory entries whose value shall become + a group name in the user's list of groups after a successful + authentication. The value of this field is case-sensitive + and must match the case of the attribute name returned by + the ActiveDirectory server in the user's entry. E.g. "cn" + for common name. Distinguished names can be used by specifying + lower-case "dn". Optional. When not specified, the default + will act as if the GroupName were specified as "dn" (distinguished + name). + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". + When not specified, no group search will be performed and authenticated + users will not belong to any groups from the ActiveDirectory + provider. Also, when not specified, the values of Filter and + Attributes are ignored. + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for groups for a user. The + pattern "{}" must occur in the filter at least once and will + be dynamically replaced by the dn (distinguished name) of the + user entry found as a result of the user search. E.g. "member={}" + or "&(objectClass=groupOfNames)(member={})". For more information + about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as "member={}". + type: string + type: object + host: + description: 'Host is the hostname of this Active Directory identity + provider, i.e., where to connect. For example: ldap.example.com:636.' + minLength: 1 + type: string + tls: + description: TLS contains the connection settings for how to establish + the connection to the Host. + properties: + certificateAuthorityData: + description: X.509 Certificate Authority (base64-encoded PEM bundle). + If omitted, a default set of system roots will be trusted. + type: string + type: object + userSearch: + description: UserSearch contains the configuration for searching for + a user by name in Active Directory. + properties: + attributes: + description: Attributes specifies how the user's information should + be read from the ActiveDirectory entry which was found as the + result of the user search. + properties: + uid: + description: UID specifies the name of the attribute in the + ActiveDirectory entry which whose value shall be used to + uniquely identify the user within this ActiveDirectory provider + after a successful authentication. Optional, when empty + this defaults to "objectGUID". + type: string + username: + description: Username specifies the name of the attribute + in the ActiveDirectory entry whose value shall become the + username of the user after a successful authentication. + This would typically be the same attribute name used in + Optional, when empty this defaults to "sAMAccountName". + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". + Optional, when not specified it will be defaulted based on the + host, for example if your active directory host is "activedirectory.example.com:636", + it will be "dc=activedirectory,dc=example,dc=com". + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for users. The pattern "{}" + must occur in the filter at least once and will be dynamically + replaced by the username for which the search is being run. + E.g. "mail={}" or "&(objectClass=person)(uid={})". For more + information about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as the + value from Attributes.Username appended by "={}". When the Attributes.Username + is set to "dn" then the Filter must be explicitly specified, + since the default value of "dn={}" would not work. + type: string + type: object + required: + - host + type: object + status: + description: Status of the identity provider. + properties: + conditions: + description: Represents the observations of an identity provider's + current state. + items: + description: Condition status of a resource (mirrored from the metav1.Condition + type added in Kubernetes 1.19). In a future API version we can + switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413. + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + phase: + default: Pending + description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + enum: + - Pending + - Ready + - Error + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/generated/1.19/README.adoc b/generated/1.19/README.adoc index 7f47bdeb..eadb1b33 100644 --- a/generated/1.19/README.adoc +++ b/generated/1.19/README.adoc @@ -748,6 +748,157 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro +[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider"] +==== ActiveDirectoryIdentityProvider + +ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderlist[$$ActiveDirectoryIdentityProviderList$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`. + +| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]__ | Spec for configuring the identity provider. +| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]__ | Status of the identity provider. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind"] +==== ActiveDirectoryIdentityProviderBind + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the username and password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password must be non-empty. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch"] +==== ActiveDirectoryIdentityProviderGroupSearch + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, the values of Filter and Attributes are ignored. +| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as "member={}". +| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes[$$ActiveDirectoryIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as the result of the group search. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes"] +==== ActiveDirectoryIdentityProviderGroupSearchAttributes + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`groupName`* __string__ | GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name in the user's list of groups after a successful authentication. The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). +|=== + + + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec"] +==== ActiveDirectoryIdentityProviderSpec + +Spec for configuring an ActiveDirectory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`host`* __string__ | Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. +| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-tlsspec[$$TLSSpec$$]__ | TLS contains the connection settings for how to establish the connection to the Host. +| *`bind`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind[$$ActiveDirectoryIdentityProviderBind$$]__ | Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. +| *`userSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$]__ | UserSearch contains the configuration for searching for a user by name in Active Directory. +| *`groupSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$]__ | GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus"] +==== ActiveDirectoryIdentityProviderStatus + +Status of an Active Directory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`phase`* __ActiveDirectoryIdentityProviderPhase__ | Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. +| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch"] +==== ActiveDirectoryIdentityProviderUserSearch + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". Optional, when not specified it will be defaulted based on the host, for example if your active directory host is "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". +| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the username for which the search is being run. E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as the value from Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be explicitly specified, since the default value of "dn={}" would not work. +| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes[$$ActiveDirectoryIdentityProviderUserSearchAttributes$$]__ | Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as the result of the user search. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes"] +==== ActiveDirectoryIdentityProviderUserSearchAttributes + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`username`* __string__ | Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username of the user after a successful authentication. This would typically be the same attribute name used in Optional, when empty this defaults to "sAMAccountName". +| *`uid`* __string__ | UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely identify the user within this ActiveDirectory provider after a successful authentication. Optional, when empty this defaults to "objectGUID". +|=== + + [id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-condition"] ==== Condition @@ -755,6 +906,7 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro .Appears In: **** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-oidcidentityproviderstatus[$$OIDCIdentityProviderStatus$$] **** @@ -1054,6 +1206,7 @@ Status of an OIDC identity provider. .Appears In: **** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-idp-v1alpha1-oidcidentityproviderspec[$$OIDCIdentityProviderSpec$$] **** diff --git a/generated/1.19/apis/supervisor/idp/v1alpha1/register.go b/generated/1.19/apis/supervisor/idp/v1alpha1/register.go index ddc9c360..e3406a81 100644 --- a/generated/1.19/apis/supervisor/idp/v1alpha1/register.go +++ b/generated/1.19/apis/supervisor/idp/v1alpha1/register.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 @@ -34,6 +34,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &OIDCIdentityProviderList{}, &LDAPIdentityProvider{}, &LDAPIdentityProviderList{}, + &ActiveDirectoryIdentityProvider{}, + &ActiveDirectoryIdentityProviderList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/generated/1.19/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go b/generated/1.19/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go new file mode 100644 index 00000000..18726e7b --- /dev/null +++ b/generated/1.19/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go @@ -0,0 +1,167 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ActiveDirectoryIdentityProviderPhase string + +const ( + // ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources. + ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending" + + // ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state. + ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready" + + // ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state. + ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error" +) + +// Status of an Active Directory identity provider. +type ActiveDirectoryIdentityProviderStatus struct { + // Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + // +kubebuilder:default=Pending + // +kubebuilder:validation:Enum=Pending;Ready;Error + Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"` + + // Represents the observations of an identity provider's current state. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +type ActiveDirectoryIdentityProviderBind struct { + // SecretName contains the name of a namespace-local Secret object that provides the username and + // password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be + // of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value + // should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + // The password must be non-empty. + // +kubebuilder:validation:MinLength=1 + SecretName string `json:"secretName"` +} + +type ActiveDirectoryIdentityProviderUserSearchAttributes struct { + // Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username + // of the user after a successful authentication. This would typically be the same attribute name used in + // Optional, when empty this defaults to "sAMAccountName". + // +optional + Username string `json:"username,omitempty"` + + // UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely + // identify the user within this ActiveDirectory provider after a successful authentication. + // Optional, when empty this defaults to "objectGUID". + // +optional + UID string `json:"uid,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearchAttributes struct { + // GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name + // in the user's list of groups after a successful authentication. + // The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory + // server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". + // Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). + // +optional + GroupName string `json:"groupName,omitempty"` +} + +type ActiveDirectoryIdentityProviderUserSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for users. + // E.g. "ou=users,dc=example,dc=com". + // Optional, when not specified it will be defaulted based on the host, for example if your active directory host is + // "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur + // in the filter at least once and will be dynamically replaced by the username for which the search is being run. + // E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as the value from + // Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be + // explicitly specified, since the default value of "dn={}" would not work. + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as + // the result of the user search. + // +optional + Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. + // "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and + // authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, + // the values of Filter and Attributes are ignored. + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. + // The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the + // dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or + // "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as "member={}". + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as + // the result of the group search. + // +optional + Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"` +} + +// Spec for configuring an ActiveDirectory identity provider. +type ActiveDirectoryIdentityProviderSpec struct { + // Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. + // +kubebuilder:validation:MinLength=1 + Host string `json:"host"` + + // TLS contains the connection settings for how to establish the connection to the Host. + TLS *TLSSpec `json:"tls,omitempty"` + + // Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server + // to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. + Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"` + + // UserSearch contains the configuration for searching for a user by name in Active Directory. + UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"` + + // GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. + GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"` +} + +// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps +// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host` +// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:subresource:status +type ActiveDirectoryIdentityProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec for configuring the identity provider. + Spec ActiveDirectoryIdentityProviderSpec `json:"spec"` + + // Status of the identity provider. + Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"` +} + +// List of ActiveDirectoryIdentityProvider objects. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ActiveDirectoryIdentityProviderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + Items []ActiveDirectoryIdentityProvider `json:"items"` +} diff --git a/generated/1.19/apis/supervisor/idp/v1alpha1/types_meta.go b/generated/1.19/apis/supervisor/idp/v1alpha1/types_meta.go index e59976ff..e04c6f2a 100644 --- a/generated/1.19/apis/supervisor/idp/v1alpha1/types_meta.go +++ b/generated/1.19/apis/supervisor/idp/v1alpha1/types_meta.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 diff --git a/generated/1.19/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go b/generated/1.19/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go index f7762b09..9895a76e 100644 --- a/generated/1.19/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.19/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go @@ -11,6 +11,196 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProvider) DeepCopyInto(out *ActiveDirectoryIdentityProvider) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProvider. +func (in *ActiveDirectoryIdentityProvider) DeepCopy() *ActiveDirectoryIdentityProvider { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProvider) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopyInto(out *ActiveDirectoryIdentityProviderBind) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderBind. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopy() *ActiveDirectoryIdentityProviderBind { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderBind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearch. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearchAttributes. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearchAttributes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyInto(out *ActiveDirectoryIdentityProviderList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ActiveDirectoryIdentityProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderList. +func (in *ActiveDirectoryIdentityProviderList) DeepCopy() *ActiveDirectoryIdentityProviderList { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopyInto(out *ActiveDirectoryIdentityProviderSpec) { + *out = *in + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLSSpec) + **out = **in + } + out.Bind = in.Bind + out.UserSearch = in.UserSearch + out.GroupSearch = in.GroupSearch + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderSpec. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopy() *ActiveDirectoryIdentityProviderSpec { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopyInto(out *ActiveDirectoryIdentityProviderStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderStatus. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopy() *ActiveDirectoryIdentityProviderStatus { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearch. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopy() *ActiveDirectoryIdentityProviderUserSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearchAttributes. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderUserSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearchAttributes) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Condition) DeepCopyInto(out *Condition) { *out = *in diff --git a/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..bf585258 --- /dev/null +++ b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,182 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "go.pinniped.dev/generated/1.19/apis/supervisor/idp/v1alpha1" + scheme "go.pinniped.dev/generated/1.19/client/supervisor/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ActiveDirectoryIdentityProvidersGetter has a method to return a ActiveDirectoryIdentityProviderInterface. +// A group's client should implement this interface. +type ActiveDirectoryIdentityProvidersGetter interface { + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface +} + +// ActiveDirectoryIdentityProviderInterface has methods to work with ActiveDirectoryIdentityProvider resources. +type ActiveDirectoryIdentityProviderInterface interface { + Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ActiveDirectoryIdentityProviderList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) + ActiveDirectoryIdentityProviderExpansion +} + +// activeDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type activeDirectoryIdentityProviders struct { + client rest.Interface + ns string +} + +// newActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviders +func newActiveDirectoryIdentityProviders(c *IDPV1alpha1Client, namespace string) *activeDirectoryIdentityProviders { + return &activeDirectoryIdentityProviders{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *activeDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *activeDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ActiveDirectoryIdentityProviderList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *activeDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Post(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *activeDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *activeDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *activeDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *activeDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go new file mode 100644 index 00000000..696aab0e --- /dev/null +++ b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go @@ -0,0 +1,129 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "go.pinniped.dev/generated/1.19/apis/supervisor/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeActiveDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type FakeActiveDirectoryIdentityProviders struct { + Fake *FakeIDPV1alpha1 + ns string +} + +var activedirectoryidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "activedirectoryidentityproviders"} + +var activedirectoryidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "ActiveDirectoryIdentityProvider"} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *FakeActiveDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(activedirectoryidentityprovidersResource, activedirectoryidentityprovidersKind, c.ns, opts), &v1alpha1.ActiveDirectoryIdentityProviderList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ActiveDirectoryIdentityProviderList{ListMeta: obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).ListMeta} + for _, item := range obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *FakeActiveDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(activedirectoryidentityprovidersResource, c.ns, opts)) + +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeActiveDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(activedirectoryidentityprovidersResource, "status", c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *FakeActiveDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeActiveDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(activedirectoryidentityprovidersResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ActiveDirectoryIdentityProviderList{}) + return err +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *FakeActiveDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(activedirectoryidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} diff --git a/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go index 28e3d63f..ea0ea195 100644 --- a/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go +++ b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go @@ -15,6 +15,10 @@ type FakeIDPV1alpha1 struct { *testing.Fake } +func (c *FakeIDPV1alpha1) ActiveDirectoryIdentityProviders(namespace string) v1alpha1.ActiveDirectoryIdentityProviderInterface { + return &FakeActiveDirectoryIdentityProviders{c, namespace} +} + func (c *FakeIDPV1alpha1) LDAPIdentityProviders(namespace string) v1alpha1.LDAPIdentityProviderInterface { return &FakeLDAPIdentityProviders{c, namespace} } diff --git a/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go index 137892f3..a7fdb511 100644 --- a/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go +++ b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go @@ -5,6 +5,8 @@ package v1alpha1 +type ActiveDirectoryIdentityProviderExpansion interface{} + type LDAPIdentityProviderExpansion interface{} type OIDCIdentityProviderExpansion interface{} diff --git a/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go index 213c0601..bfdf55a3 100644 --- a/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go +++ b/generated/1.19/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go @@ -13,6 +13,7 @@ import ( type IDPV1alpha1Interface interface { RESTClient() rest.Interface + ActiveDirectoryIdentityProvidersGetter LDAPIdentityProvidersGetter OIDCIdentityProvidersGetter } @@ -22,6 +23,10 @@ type IDPV1alpha1Client struct { restClient rest.Interface } +func (c *IDPV1alpha1Client) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface { + return newActiveDirectoryIdentityProviders(c, namespace) +} + func (c *IDPV1alpha1Client) LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface { return newLDAPIdentityProviders(c, namespace) } diff --git a/generated/1.19/client/supervisor/informers/externalversions/generic.go b/generated/1.19/client/supervisor/informers/externalversions/generic.go index 8308f3a9..77b758f2 100644 --- a/generated/1.19/client/supervisor/informers/externalversions/generic.go +++ b/generated/1.19/client/supervisor/informers/externalversions/generic.go @@ -45,6 +45,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().FederationDomains().Informer()}, nil // Group=idp.supervisor.pinniped.dev, Version=v1alpha1 + case idpv1alpha1.SchemeGroupVersion.WithResource("activedirectoryidentityproviders"): + return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().ActiveDirectoryIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("ldapidentityproviders"): return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().LDAPIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("oidcidentityproviders"): diff --git a/generated/1.19/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.19/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..6601bd4b --- /dev/null +++ b/generated/1.19/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,77 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + idpv1alpha1 "go.pinniped.dev/generated/1.19/apis/supervisor/idp/v1alpha1" + versioned "go.pinniped.dev/generated/1.19/client/supervisor/clientset/versioned" + internalinterfaces "go.pinniped.dev/generated/1.19/client/supervisor/informers/externalversions/internalinterfaces" + v1alpha1 "go.pinniped.dev/generated/1.19/client/supervisor/listers/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderInformer provides access to a shared informer and lister for +// ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ActiveDirectoryIdentityProviderLister +} + +type activeDirectoryIdentityProviderInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).Watch(context.TODO(), options) + }, + }, + &idpv1alpha1.ActiveDirectoryIdentityProvider{}, + resyncPeriod, + indexers, + ) +} + +func (f *activeDirectoryIdentityProviderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *activeDirectoryIdentityProviderInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&idpv1alpha1.ActiveDirectoryIdentityProvider{}, f.defaultInformer) +} + +func (f *activeDirectoryIdentityProviderInformer) Lister() v1alpha1.ActiveDirectoryIdentityProviderLister { + return v1alpha1.NewActiveDirectoryIdentityProviderLister(f.Informer().GetIndexer()) +} diff --git a/generated/1.19/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go b/generated/1.19/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go index 1b3a9f24..dda26a61 100644 --- a/generated/1.19/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go +++ b/generated/1.19/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go @@ -11,6 +11,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. + ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. LDAPIdentityProviders() LDAPIdentityProviderInformer // OIDCIdentityProviders returns a OIDCIdentityProviderInformer. @@ -28,6 +30,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. +func (v *version) ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer { + return &activeDirectoryIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. func (v *version) LDAPIdentityProviders() LDAPIdentityProviderInformer { return &lDAPIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/generated/1.19/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.19/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..21cbeee5 --- /dev/null +++ b/generated/1.19/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,86 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "go.pinniped.dev/generated/1.19/apis/supervisor/idp/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderLister helps list ActiveDirectoryIdentityProviders. +// All objects returned here must be treated as read-only. +type ActiveDirectoryIdentityProviderLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister + ActiveDirectoryIdentityProviderListerExpansion +} + +// activeDirectoryIdentityProviderLister implements the ActiveDirectoryIdentityProviderLister interface. +type activeDirectoryIdentityProviderLister struct { + indexer cache.Indexer +} + +// NewActiveDirectoryIdentityProviderLister returns a new ActiveDirectoryIdentityProviderLister. +func NewActiveDirectoryIdentityProviderLister(indexer cache.Indexer) ActiveDirectoryIdentityProviderLister { + return &activeDirectoryIdentityProviderLister{indexer: indexer} +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer. +func (s *activeDirectoryIdentityProviderLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. +func (s *activeDirectoryIdentityProviderLister) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister { + return activeDirectoryIdentityProviderNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ActiveDirectoryIdentityProviderNamespaceLister helps list and get ActiveDirectoryIdentityProviders. +// All objects returned here must be treated as read-only. +type ActiveDirectoryIdentityProviderNamespaceLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + ActiveDirectoryIdentityProviderNamespaceListerExpansion +} + +// activeDirectoryIdentityProviderNamespaceLister implements the ActiveDirectoryIdentityProviderNamespaceLister +// interface. +type activeDirectoryIdentityProviderNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. +func (s activeDirectoryIdentityProviderNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. +func (s activeDirectoryIdentityProviderNamespaceLister) Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("activedirectoryidentityprovider"), name) + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), nil +} diff --git a/generated/1.19/client/supervisor/listers/idp/v1alpha1/expansion_generated.go b/generated/1.19/client/supervisor/listers/idp/v1alpha1/expansion_generated.go index 28f41bd7..7c625e80 100644 --- a/generated/1.19/client/supervisor/listers/idp/v1alpha1/expansion_generated.go +++ b/generated/1.19/client/supervisor/listers/idp/v1alpha1/expansion_generated.go @@ -5,6 +5,14 @@ package v1alpha1 +// ActiveDirectoryIdentityProviderListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderLister. +type ActiveDirectoryIdentityProviderListerExpansion interface{} + +// ActiveDirectoryIdentityProviderNamespaceListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderNamespaceLister. +type ActiveDirectoryIdentityProviderNamespaceListerExpansion interface{} + // LDAPIdentityProviderListerExpansion allows custom methods to be added to // LDAPIdentityProviderLister. type LDAPIdentityProviderListerExpansion interface{} diff --git a/generated/1.19/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml b/generated/1.19/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml new file mode 100644 index 00000000..03fbcd08 --- /dev/null +++ b/generated/1.19/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml @@ -0,0 +1,271 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev +spec: + group: idp.supervisor.pinniped.dev + names: + categories: + - pinniped + - pinniped-idp + - pinniped-idps + kind: ActiveDirectoryIdentityProvider + listKind: ActiveDirectoryIdentityProviderList + plural: activedirectoryidentityproviders + singular: activedirectoryidentityprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.host + name: Host + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ActiveDirectoryIdentityProvider describes the configuration of + an upstream Microsoft Active Directory identity provider. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec for configuring the identity provider. + properties: + bind: + description: Bind contains the configuration for how to provide access + credentials during an initial bind to the ActiveDirectory server + to be allowed to perform searches and binds to validate a user's + credentials during a user's authentication attempt. + properties: + secretName: + description: SecretName contains the name of a namespace-local + Secret object that provides the username and password for an + Active Directory bind user. This account will be used to perform + LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" + which includes "username" and "password" keys. The username + value should be the full dn (distinguished name) of your bind + account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + The password must be non-empty. + minLength: 1 + type: string + required: + - secretName + type: object + groupSearch: + description: GroupSearch contains the configuration for searching + for a user's group membership in ActiveDirectory. + properties: + attributes: + description: Attributes specifies how the group's information + should be read from each ActiveDirectory entry which was found + as the result of the group search. + properties: + groupName: + description: GroupName specifies the name of the attribute + in the Active Directory entries whose value shall become + a group name in the user's list of groups after a successful + authentication. The value of this field is case-sensitive + and must match the case of the attribute name returned by + the ActiveDirectory server in the user's entry. E.g. "cn" + for common name. Distinguished names can be used by specifying + lower-case "dn". Optional. When not specified, the default + will act as if the GroupName were specified as "dn" (distinguished + name). + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". + When not specified, no group search will be performed and authenticated + users will not belong to any groups from the ActiveDirectory + provider. Also, when not specified, the values of Filter and + Attributes are ignored. + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for groups for a user. The + pattern "{}" must occur in the filter at least once and will + be dynamically replaced by the dn (distinguished name) of the + user entry found as a result of the user search. E.g. "member={}" + or "&(objectClass=groupOfNames)(member={})". For more information + about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as "member={}". + type: string + type: object + host: + description: 'Host is the hostname of this Active Directory identity + provider, i.e., where to connect. For example: ldap.example.com:636.' + minLength: 1 + type: string + tls: + description: TLS contains the connection settings for how to establish + the connection to the Host. + properties: + certificateAuthorityData: + description: X.509 Certificate Authority (base64-encoded PEM bundle). + If omitted, a default set of system roots will be trusted. + type: string + type: object + userSearch: + description: UserSearch contains the configuration for searching for + a user by name in Active Directory. + properties: + attributes: + description: Attributes specifies how the user's information should + be read from the ActiveDirectory entry which was found as the + result of the user search. + properties: + uid: + description: UID specifies the name of the attribute in the + ActiveDirectory entry which whose value shall be used to + uniquely identify the user within this ActiveDirectory provider + after a successful authentication. Optional, when empty + this defaults to "objectGUID". + type: string + username: + description: Username specifies the name of the attribute + in the ActiveDirectory entry whose value shall become the + username of the user after a successful authentication. + This would typically be the same attribute name used in + Optional, when empty this defaults to "sAMAccountName". + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". + Optional, when not specified it will be defaulted based on the + host, for example if your active directory host is "activedirectory.example.com:636", + it will be "dc=activedirectory,dc=example,dc=com". + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for users. The pattern "{}" + must occur in the filter at least once and will be dynamically + replaced by the username for which the search is being run. + E.g. "mail={}" or "&(objectClass=person)(uid={})". For more + information about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as the + value from Attributes.Username appended by "={}". When the Attributes.Username + is set to "dn" then the Filter must be explicitly specified, + since the default value of "dn={}" would not work. + type: string + type: object + required: + - host + type: object + status: + description: Status of the identity provider. + properties: + conditions: + description: Represents the observations of an identity provider's + current state. + items: + description: Condition status of a resource (mirrored from the metav1.Condition + type added in Kubernetes 1.19). In a future API version we can + switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413. + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + phase: + default: Pending + description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + enum: + - Pending + - Ready + - Error + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/generated/1.20/README.adoc b/generated/1.20/README.adoc index 1bcf7d08..13051452 100644 --- a/generated/1.20/README.adoc +++ b/generated/1.20/README.adoc @@ -748,6 +748,157 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro +[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider"] +==== ActiveDirectoryIdentityProvider + +ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderlist[$$ActiveDirectoryIdentityProviderList$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`metadata`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.2/#objectmeta-v1-meta[$$ObjectMeta$$]__ | Refer to Kubernetes API documentation for fields of `metadata`. + +| *`spec`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$]__ | Spec for configuring the identity provider. +| *`status`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$]__ | Status of the identity provider. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind"] +==== ActiveDirectoryIdentityProviderBind + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`secretName`* __string__ | SecretName contains the name of a namespace-local Secret object that provides the username and password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password must be non-empty. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch"] +==== ActiveDirectoryIdentityProviderGroupSearch + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, the values of Filter and Attributes are ignored. +| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as "member={}". +| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes[$$ActiveDirectoryIdentityProviderGroupSearchAttributes$$]__ | Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as the result of the group search. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearchattributes"] +==== ActiveDirectoryIdentityProviderGroupSearchAttributes + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`groupName`* __string__ | GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name in the user's list of groups after a successful authentication. The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). +|=== + + + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec"] +==== ActiveDirectoryIdentityProviderSpec + +Spec for configuring an ActiveDirectory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`host`* __string__ | Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. +| *`tls`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-tlsspec[$$TLSSpec$$]__ | TLS contains the connection settings for how to establish the connection to the Host. +| *`bind`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderbind[$$ActiveDirectoryIdentityProviderBind$$]__ | Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. +| *`userSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$]__ | UserSearch contains the configuration for searching for a user by name in Active Directory. +| *`groupSearch`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovidergroupsearch[$$ActiveDirectoryIdentityProviderGroupSearch$$]__ | GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus"] +==== ActiveDirectoryIdentityProviderStatus + +Status of an Active Directory identity provider. + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityprovider[$$ActiveDirectoryIdentityProvider$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`phase`* __ActiveDirectoryIdentityProviderPhase__ | Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. +| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an identity provider's current state. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch"] +==== ActiveDirectoryIdentityProviderUserSearch + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`base`* __string__ | Base is the dn (distinguished name) that should be used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". Optional, when not specified it will be defaulted based on the host, for example if your active directory host is "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". +| *`filter`* __string__ | Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the username for which the search is being run. E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters. Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. Optional. When not specified, the default will act as if the Filter were specified as the value from Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be explicitly specified, since the default value of "dn={}" would not work. +| *`attributes`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes[$$ActiveDirectoryIdentityProviderUserSearchAttributes$$]__ | Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as the result of the user search. +|=== + + +[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearchattributes"] +==== ActiveDirectoryIdentityProviderUserSearchAttributes + + + +.Appears In: +**** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderusersearch[$$ActiveDirectoryIdentityProviderUserSearch$$] +**** + +[cols="25a,75a", options="header"] +|=== +| Field | Description +| *`username`* __string__ | Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username of the user after a successful authentication. This would typically be the same attribute name used in Optional, when empty this defaults to "sAMAccountName". +| *`uid`* __string__ | UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely identify the user within this ActiveDirectory provider after a successful authentication. Optional, when empty this defaults to "objectGUID". +|=== + + [id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-condition"] ==== Condition @@ -755,6 +906,7 @@ Package v1alpha1 is the v1alpha1 version of the Pinniped supervisor identity pro .Appears In: **** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderstatus[$$ActiveDirectoryIdentityProviderStatus$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-ldapidentityproviderstatus[$$LDAPIdentityProviderStatus$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-oidcidentityproviderstatus[$$OIDCIdentityProviderStatus$$] **** @@ -1054,6 +1206,7 @@ Status of an OIDC identity provider. .Appears In: **** +- xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-activedirectoryidentityproviderspec[$$ActiveDirectoryIdentityProviderSpec$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-ldapidentityproviderspec[$$LDAPIdentityProviderSpec$$] - xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-idp-v1alpha1-oidcidentityproviderspec[$$OIDCIdentityProviderSpec$$] **** diff --git a/generated/1.20/apis/supervisor/idp/v1alpha1/register.go b/generated/1.20/apis/supervisor/idp/v1alpha1/register.go index ddc9c360..e3406a81 100644 --- a/generated/1.20/apis/supervisor/idp/v1alpha1/register.go +++ b/generated/1.20/apis/supervisor/idp/v1alpha1/register.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 @@ -34,6 +34,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &OIDCIdentityProviderList{}, &LDAPIdentityProvider{}, &LDAPIdentityProviderList{}, + &ActiveDirectoryIdentityProvider{}, + &ActiveDirectoryIdentityProviderList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/generated/1.20/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go b/generated/1.20/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go new file mode 100644 index 00000000..18726e7b --- /dev/null +++ b/generated/1.20/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go @@ -0,0 +1,167 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ActiveDirectoryIdentityProviderPhase string + +const ( + // ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources. + ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending" + + // ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state. + ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready" + + // ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state. + ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error" +) + +// Status of an Active Directory identity provider. +type ActiveDirectoryIdentityProviderStatus struct { + // Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + // +kubebuilder:default=Pending + // +kubebuilder:validation:Enum=Pending;Ready;Error + Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"` + + // Represents the observations of an identity provider's current state. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +type ActiveDirectoryIdentityProviderBind struct { + // SecretName contains the name of a namespace-local Secret object that provides the username and + // password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be + // of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value + // should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + // The password must be non-empty. + // +kubebuilder:validation:MinLength=1 + SecretName string `json:"secretName"` +} + +type ActiveDirectoryIdentityProviderUserSearchAttributes struct { + // Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username + // of the user after a successful authentication. This would typically be the same attribute name used in + // Optional, when empty this defaults to "sAMAccountName". + // +optional + Username string `json:"username,omitempty"` + + // UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely + // identify the user within this ActiveDirectory provider after a successful authentication. + // Optional, when empty this defaults to "objectGUID". + // +optional + UID string `json:"uid,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearchAttributes struct { + // GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name + // in the user's list of groups after a successful authentication. + // The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory + // server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". + // Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). + // +optional + GroupName string `json:"groupName,omitempty"` +} + +type ActiveDirectoryIdentityProviderUserSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for users. + // E.g. "ou=users,dc=example,dc=com". + // Optional, when not specified it will be defaulted based on the host, for example if your active directory host is + // "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur + // in the filter at least once and will be dynamically replaced by the username for which the search is being run. + // E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as the value from + // Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be + // explicitly specified, since the default value of "dn={}" would not work. + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as + // the result of the user search. + // +optional + Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. + // "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and + // authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, + // the values of Filter and Attributes are ignored. + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. + // The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the + // dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or + // "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as "member={}". + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as + // the result of the group search. + // +optional + Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"` +} + +// Spec for configuring an ActiveDirectory identity provider. +type ActiveDirectoryIdentityProviderSpec struct { + // Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. + // +kubebuilder:validation:MinLength=1 + Host string `json:"host"` + + // TLS contains the connection settings for how to establish the connection to the Host. + TLS *TLSSpec `json:"tls,omitempty"` + + // Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server + // to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. + Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"` + + // UserSearch contains the configuration for searching for a user by name in Active Directory. + UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"` + + // GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. + GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"` +} + +// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps +// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host` +// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:subresource:status +type ActiveDirectoryIdentityProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec for configuring the identity provider. + Spec ActiveDirectoryIdentityProviderSpec `json:"spec"` + + // Status of the identity provider. + Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"` +} + +// List of ActiveDirectoryIdentityProvider objects. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ActiveDirectoryIdentityProviderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + Items []ActiveDirectoryIdentityProvider `json:"items"` +} diff --git a/generated/1.20/apis/supervisor/idp/v1alpha1/types_meta.go b/generated/1.20/apis/supervisor/idp/v1alpha1/types_meta.go index e59976ff..e04c6f2a 100644 --- a/generated/1.20/apis/supervisor/idp/v1alpha1/types_meta.go +++ b/generated/1.20/apis/supervisor/idp/v1alpha1/types_meta.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 diff --git a/generated/1.20/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go b/generated/1.20/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go index f7762b09..9895a76e 100644 --- a/generated/1.20/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go +++ b/generated/1.20/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go @@ -11,6 +11,196 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProvider) DeepCopyInto(out *ActiveDirectoryIdentityProvider) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProvider. +func (in *ActiveDirectoryIdentityProvider) DeepCopy() *ActiveDirectoryIdentityProvider { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProvider) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopyInto(out *ActiveDirectoryIdentityProviderBind) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderBind. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopy() *ActiveDirectoryIdentityProviderBind { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderBind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearch. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearchAttributes. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearchAttributes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyInto(out *ActiveDirectoryIdentityProviderList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ActiveDirectoryIdentityProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderList. +func (in *ActiveDirectoryIdentityProviderList) DeepCopy() *ActiveDirectoryIdentityProviderList { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopyInto(out *ActiveDirectoryIdentityProviderSpec) { + *out = *in + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLSSpec) + **out = **in + } + out.Bind = in.Bind + out.UserSearch = in.UserSearch + out.GroupSearch = in.GroupSearch + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderSpec. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopy() *ActiveDirectoryIdentityProviderSpec { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopyInto(out *ActiveDirectoryIdentityProviderStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderStatus. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopy() *ActiveDirectoryIdentityProviderStatus { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearch. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopy() *ActiveDirectoryIdentityProviderUserSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearchAttributes. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderUserSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearchAttributes) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Condition) DeepCopyInto(out *Condition) { *out = *in diff --git a/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..2958cb14 --- /dev/null +++ b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,182 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "go.pinniped.dev/generated/1.20/apis/supervisor/idp/v1alpha1" + scheme "go.pinniped.dev/generated/1.20/client/supervisor/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ActiveDirectoryIdentityProvidersGetter has a method to return a ActiveDirectoryIdentityProviderInterface. +// A group's client should implement this interface. +type ActiveDirectoryIdentityProvidersGetter interface { + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface +} + +// ActiveDirectoryIdentityProviderInterface has methods to work with ActiveDirectoryIdentityProvider resources. +type ActiveDirectoryIdentityProviderInterface interface { + Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ActiveDirectoryIdentityProviderList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) + ActiveDirectoryIdentityProviderExpansion +} + +// activeDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type activeDirectoryIdentityProviders struct { + client rest.Interface + ns string +} + +// newActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviders +func newActiveDirectoryIdentityProviders(c *IDPV1alpha1Client, namespace string) *activeDirectoryIdentityProviders { + return &activeDirectoryIdentityProviders{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *activeDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *activeDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ActiveDirectoryIdentityProviderList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *activeDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Post(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *activeDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *activeDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *activeDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *activeDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go new file mode 100644 index 00000000..27ace5a2 --- /dev/null +++ b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go @@ -0,0 +1,129 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "go.pinniped.dev/generated/1.20/apis/supervisor/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeActiveDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type FakeActiveDirectoryIdentityProviders struct { + Fake *FakeIDPV1alpha1 + ns string +} + +var activedirectoryidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "activedirectoryidentityproviders"} + +var activedirectoryidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "ActiveDirectoryIdentityProvider"} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *FakeActiveDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(activedirectoryidentityprovidersResource, activedirectoryidentityprovidersKind, c.ns, opts), &v1alpha1.ActiveDirectoryIdentityProviderList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ActiveDirectoryIdentityProviderList{ListMeta: obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).ListMeta} + for _, item := range obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *FakeActiveDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(activedirectoryidentityprovidersResource, c.ns, opts)) + +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeActiveDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(activedirectoryidentityprovidersResource, "status", c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *FakeActiveDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeActiveDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(activedirectoryidentityprovidersResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ActiveDirectoryIdentityProviderList{}) + return err +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *FakeActiveDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(activedirectoryidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} diff --git a/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go index 5e927831..ff95d783 100644 --- a/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go +++ b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go @@ -15,6 +15,10 @@ type FakeIDPV1alpha1 struct { *testing.Fake } +func (c *FakeIDPV1alpha1) ActiveDirectoryIdentityProviders(namespace string) v1alpha1.ActiveDirectoryIdentityProviderInterface { + return &FakeActiveDirectoryIdentityProviders{c, namespace} +} + func (c *FakeIDPV1alpha1) LDAPIdentityProviders(namespace string) v1alpha1.LDAPIdentityProviderInterface { return &FakeLDAPIdentityProviders{c, namespace} } diff --git a/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go index 137892f3..a7fdb511 100644 --- a/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go +++ b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go @@ -5,6 +5,8 @@ package v1alpha1 +type ActiveDirectoryIdentityProviderExpansion interface{} + type LDAPIdentityProviderExpansion interface{} type OIDCIdentityProviderExpansion interface{} diff --git a/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go index 900f258a..fa865322 100644 --- a/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go +++ b/generated/1.20/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go @@ -13,6 +13,7 @@ import ( type IDPV1alpha1Interface interface { RESTClient() rest.Interface + ActiveDirectoryIdentityProvidersGetter LDAPIdentityProvidersGetter OIDCIdentityProvidersGetter } @@ -22,6 +23,10 @@ type IDPV1alpha1Client struct { restClient rest.Interface } +func (c *IDPV1alpha1Client) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface { + return newActiveDirectoryIdentityProviders(c, namespace) +} + func (c *IDPV1alpha1Client) LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface { return newLDAPIdentityProviders(c, namespace) } diff --git a/generated/1.20/client/supervisor/informers/externalversions/generic.go b/generated/1.20/client/supervisor/informers/externalversions/generic.go index b7821644..f8460123 100644 --- a/generated/1.20/client/supervisor/informers/externalversions/generic.go +++ b/generated/1.20/client/supervisor/informers/externalversions/generic.go @@ -45,6 +45,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().FederationDomains().Informer()}, nil // Group=idp.supervisor.pinniped.dev, Version=v1alpha1 + case idpv1alpha1.SchemeGroupVersion.WithResource("activedirectoryidentityproviders"): + return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().ActiveDirectoryIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("ldapidentityproviders"): return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().LDAPIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("oidcidentityproviders"): diff --git a/generated/1.20/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.20/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..2d620294 --- /dev/null +++ b/generated/1.20/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,77 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + idpv1alpha1 "go.pinniped.dev/generated/1.20/apis/supervisor/idp/v1alpha1" + versioned "go.pinniped.dev/generated/1.20/client/supervisor/clientset/versioned" + internalinterfaces "go.pinniped.dev/generated/1.20/client/supervisor/informers/externalversions/internalinterfaces" + v1alpha1 "go.pinniped.dev/generated/1.20/client/supervisor/listers/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderInformer provides access to a shared informer and lister for +// ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ActiveDirectoryIdentityProviderLister +} + +type activeDirectoryIdentityProviderInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).Watch(context.TODO(), options) + }, + }, + &idpv1alpha1.ActiveDirectoryIdentityProvider{}, + resyncPeriod, + indexers, + ) +} + +func (f *activeDirectoryIdentityProviderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *activeDirectoryIdentityProviderInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&idpv1alpha1.ActiveDirectoryIdentityProvider{}, f.defaultInformer) +} + +func (f *activeDirectoryIdentityProviderInformer) Lister() v1alpha1.ActiveDirectoryIdentityProviderLister { + return v1alpha1.NewActiveDirectoryIdentityProviderLister(f.Informer().GetIndexer()) +} diff --git a/generated/1.20/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go b/generated/1.20/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go index 34f8361f..5bd81fac 100644 --- a/generated/1.20/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go +++ b/generated/1.20/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go @@ -11,6 +11,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. + ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. LDAPIdentityProviders() LDAPIdentityProviderInformer // OIDCIdentityProviders returns a OIDCIdentityProviderInformer. @@ -28,6 +30,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. +func (v *version) ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer { + return &activeDirectoryIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. func (v *version) LDAPIdentityProviders() LDAPIdentityProviderInformer { return &lDAPIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/generated/1.20/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/1.20/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..7008d59a --- /dev/null +++ b/generated/1.20/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,86 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "go.pinniped.dev/generated/1.20/apis/supervisor/idp/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderLister helps list ActiveDirectoryIdentityProviders. +// All objects returned here must be treated as read-only. +type ActiveDirectoryIdentityProviderLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister + ActiveDirectoryIdentityProviderListerExpansion +} + +// activeDirectoryIdentityProviderLister implements the ActiveDirectoryIdentityProviderLister interface. +type activeDirectoryIdentityProviderLister struct { + indexer cache.Indexer +} + +// NewActiveDirectoryIdentityProviderLister returns a new ActiveDirectoryIdentityProviderLister. +func NewActiveDirectoryIdentityProviderLister(indexer cache.Indexer) ActiveDirectoryIdentityProviderLister { + return &activeDirectoryIdentityProviderLister{indexer: indexer} +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer. +func (s *activeDirectoryIdentityProviderLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. +func (s *activeDirectoryIdentityProviderLister) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister { + return activeDirectoryIdentityProviderNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ActiveDirectoryIdentityProviderNamespaceLister helps list and get ActiveDirectoryIdentityProviders. +// All objects returned here must be treated as read-only. +type ActiveDirectoryIdentityProviderNamespaceLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + ActiveDirectoryIdentityProviderNamespaceListerExpansion +} + +// activeDirectoryIdentityProviderNamespaceLister implements the ActiveDirectoryIdentityProviderNamespaceLister +// interface. +type activeDirectoryIdentityProviderNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. +func (s activeDirectoryIdentityProviderNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. +func (s activeDirectoryIdentityProviderNamespaceLister) Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("activedirectoryidentityprovider"), name) + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), nil +} diff --git a/generated/1.20/client/supervisor/listers/idp/v1alpha1/expansion_generated.go b/generated/1.20/client/supervisor/listers/idp/v1alpha1/expansion_generated.go index 28f41bd7..7c625e80 100644 --- a/generated/1.20/client/supervisor/listers/idp/v1alpha1/expansion_generated.go +++ b/generated/1.20/client/supervisor/listers/idp/v1alpha1/expansion_generated.go @@ -5,6 +5,14 @@ package v1alpha1 +// ActiveDirectoryIdentityProviderListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderLister. +type ActiveDirectoryIdentityProviderListerExpansion interface{} + +// ActiveDirectoryIdentityProviderNamespaceListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderNamespaceLister. +type ActiveDirectoryIdentityProviderNamespaceListerExpansion interface{} + // LDAPIdentityProviderListerExpansion allows custom methods to be added to // LDAPIdentityProviderLister. type LDAPIdentityProviderListerExpansion interface{} diff --git a/generated/1.20/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml b/generated/1.20/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml new file mode 100644 index 00000000..03fbcd08 --- /dev/null +++ b/generated/1.20/crds/idp.supervisor.pinniped.dev_activedirectoryidentityproviders.yaml @@ -0,0 +1,271 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev +spec: + group: idp.supervisor.pinniped.dev + names: + categories: + - pinniped + - pinniped-idp + - pinniped-idps + kind: ActiveDirectoryIdentityProvider + listKind: ActiveDirectoryIdentityProviderList + plural: activedirectoryidentityproviders + singular: activedirectoryidentityprovider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.host + name: Host + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ActiveDirectoryIdentityProvider describes the configuration of + an upstream Microsoft Active Directory identity provider. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec for configuring the identity provider. + properties: + bind: + description: Bind contains the configuration for how to provide access + credentials during an initial bind to the ActiveDirectory server + to be allowed to perform searches and binds to validate a user's + credentials during a user's authentication attempt. + properties: + secretName: + description: SecretName contains the name of a namespace-local + Secret object that provides the username and password for an + Active Directory bind user. This account will be used to perform + LDAP searches. The Secret should be of type "kubernetes.io/basic-auth" + which includes "username" and "password" keys. The username + value should be the full dn (distinguished name) of your bind + account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + The password must be non-empty. + minLength: 1 + type: string + required: + - secretName + type: object + groupSearch: + description: GroupSearch contains the configuration for searching + for a user's group membership in ActiveDirectory. + properties: + attributes: + description: Attributes specifies how the group's information + should be read from each ActiveDirectory entry which was found + as the result of the group search. + properties: + groupName: + description: GroupName specifies the name of the attribute + in the Active Directory entries whose value shall become + a group name in the user's list of groups after a successful + authentication. The value of this field is case-sensitive + and must match the case of the attribute name returned by + the ActiveDirectory server in the user's entry. E.g. "cn" + for common name. Distinguished names can be used by specifying + lower-case "dn". Optional. When not specified, the default + will act as if the GroupName were specified as "dn" (distinguished + name). + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com". + When not specified, no group search will be performed and authenticated + users will not belong to any groups from the ActiveDirectory + provider. Also, when not specified, the values of Filter and + Attributes are ignored. + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for groups for a user. The + pattern "{}" must occur in the filter at least once and will + be dynamically replaced by the dn (distinguished name) of the + user entry found as a result of the user search. E.g. "member={}" + or "&(objectClass=groupOfNames)(member={})". For more information + about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as "member={}". + type: string + type: object + host: + description: 'Host is the hostname of this Active Directory identity + provider, i.e., where to connect. For example: ldap.example.com:636.' + minLength: 1 + type: string + tls: + description: TLS contains the connection settings for how to establish + the connection to the Host. + properties: + certificateAuthorityData: + description: X.509 Certificate Authority (base64-encoded PEM bundle). + If omitted, a default set of system roots will be trusted. + type: string + type: object + userSearch: + description: UserSearch contains the configuration for searching for + a user by name in Active Directory. + properties: + attributes: + description: Attributes specifies how the user's information should + be read from the ActiveDirectory entry which was found as the + result of the user search. + properties: + uid: + description: UID specifies the name of the attribute in the + ActiveDirectory entry which whose value shall be used to + uniquely identify the user within this ActiveDirectory provider + after a successful authentication. Optional, when empty + this defaults to "objectGUID". + type: string + username: + description: Username specifies the name of the attribute + in the ActiveDirectory entry whose value shall become the + username of the user after a successful authentication. + This would typically be the same attribute name used in + Optional, when empty this defaults to "sAMAccountName". + type: string + type: object + base: + description: Base is the dn (distinguished name) that should be + used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com". + Optional, when not specified it will be defaulted based on the + host, for example if your active directory host is "activedirectory.example.com:636", + it will be "dc=activedirectory,dc=example,dc=com". + type: string + filter: + description: Filter is the ActiveDirectory search filter which + should be applied when searching for users. The pattern "{}" + must occur in the filter at least once and will be dynamically + replaced by the username for which the search is being run. + E.g. "mail={}" or "&(objectClass=person)(uid={})". For more + information about ActiveDirectory filters, see https://ldap.com/ldap-filters. + Note that the dn (distinguished name) is not an attribute of + an entry, so "dn={}" cannot be used. Optional. When not specified, + the default will act as if the Filter were specified as the + value from Attributes.Username appended by "={}". When the Attributes.Username + is set to "dn" then the Filter must be explicitly specified, + since the default value of "dn={}" would not work. + type: string + type: object + required: + - host + type: object + status: + description: Status of the identity provider. + properties: + conditions: + description: Represents the observations of an identity provider's + current state. + items: + description: Condition status of a resource (mirrored from the metav1.Condition + type added in Kubernetes 1.19). In a future API version we can + switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413. + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + phase: + default: Pending + description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + enum: + - Pending + - Ready + - Error + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/generated/latest/apis/supervisor/idp/v1alpha1/register.go b/generated/latest/apis/supervisor/idp/v1alpha1/register.go index ddc9c360..e3406a81 100644 --- a/generated/latest/apis/supervisor/idp/v1alpha1/register.go +++ b/generated/latest/apis/supervisor/idp/v1alpha1/register.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 @@ -34,6 +34,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &OIDCIdentityProviderList{}, &LDAPIdentityProvider{}, &LDAPIdentityProviderList{}, + &ActiveDirectoryIdentityProvider{}, + &ActiveDirectoryIdentityProviderList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/generated/latest/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go b/generated/latest/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go new file mode 100644 index 00000000..18726e7b --- /dev/null +++ b/generated/latest/apis/supervisor/idp/v1alpha1/types_activedirectoryidentityprovider.go @@ -0,0 +1,167 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ActiveDirectoryIdentityProviderPhase string + +const ( + // ActiveDirectoryPhasePending is the default phase for newly-created ActiveDirectoryIdentityProvider resources. + ActiveDirectoryPhasePending ActiveDirectoryIdentityProviderPhase = "Pending" + + // ActiveDirectoryPhaseReady is the phase for an ActiveDirectoryIdentityProvider resource in a healthy state. + ActiveDirectoryPhaseReady ActiveDirectoryIdentityProviderPhase = "Ready" + + // ActiveDirectoryPhaseError is the phase for an ActiveDirectoryIdentityProvider in an unhealthy state. + ActiveDirectoryPhaseError ActiveDirectoryIdentityProviderPhase = "Error" +) + +// Status of an Active Directory identity provider. +type ActiveDirectoryIdentityProviderStatus struct { + // Phase summarizes the overall status of the ActiveDirectoryIdentityProvider. + // +kubebuilder:default=Pending + // +kubebuilder:validation:Enum=Pending;Ready;Error + Phase ActiveDirectoryIdentityProviderPhase `json:"phase,omitempty"` + + // Represents the observations of an identity provider's current state. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +type ActiveDirectoryIdentityProviderBind struct { + // SecretName contains the name of a namespace-local Secret object that provides the username and + // password for an Active Directory bind user. This account will be used to perform LDAP searches. The Secret should be + // of type "kubernetes.io/basic-auth" which includes "username" and "password" keys. The username value + // should be the full dn (distinguished name) of your bind account, e.g. "cn=bind-account,ou=users,dc=example,dc=com". + // The password must be non-empty. + // +kubebuilder:validation:MinLength=1 + SecretName string `json:"secretName"` +} + +type ActiveDirectoryIdentityProviderUserSearchAttributes struct { + // Username specifies the name of the attribute in the ActiveDirectory entry whose value shall become the username + // of the user after a successful authentication. This would typically be the same attribute name used in + // Optional, when empty this defaults to "sAMAccountName". + // +optional + Username string `json:"username,omitempty"` + + // UID specifies the name of the attribute in the ActiveDirectory entry which whose value shall be used to uniquely + // identify the user within this ActiveDirectory provider after a successful authentication. + // Optional, when empty this defaults to "objectGUID". + // +optional + UID string `json:"uid,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearchAttributes struct { + // GroupName specifies the name of the attribute in the Active Directory entries whose value shall become a group name + // in the user's list of groups after a successful authentication. + // The value of this field is case-sensitive and must match the case of the attribute name returned by the ActiveDirectory + // server in the user's entry. E.g. "cn" for common name. Distinguished names can be used by specifying lower-case "dn". + // Optional. When not specified, the default will act as if the GroupName were specified as "dn" (distinguished name). + // +optional + GroupName string `json:"groupName,omitempty"` +} + +type ActiveDirectoryIdentityProviderUserSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for users. + // E.g. "ou=users,dc=example,dc=com". + // Optional, when not specified it will be defaulted based on the host, for example if your active directory host is + // "activedirectory.example.com:636", it will be "dc=activedirectory,dc=example,dc=com". + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for users. The pattern "{}" must occur + // in the filter at least once and will be dynamically replaced by the username for which the search is being run. + // E.g. "mail={}" or "&(objectClass=person)(uid={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as the value from + // Attributes.Username appended by "={}". When the Attributes.Username is set to "dn" then the Filter must be + // explicitly specified, since the default value of "dn={}" would not work. + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the user's information should be read from the ActiveDirectory entry which was found as + // the result of the user search. + // +optional + Attributes ActiveDirectoryIdentityProviderUserSearchAttributes `json:"attributes,omitempty"` +} + +type ActiveDirectoryIdentityProviderGroupSearch struct { + // Base is the dn (distinguished name) that should be used as the search base when searching for groups. E.g. + // "ou=groups,dc=example,dc=com". When not specified, no group search will be performed and + // authenticated users will not belong to any groups from the ActiveDirectory provider. Also, when not specified, + // the values of Filter and Attributes are ignored. + // +optional + Base string `json:"base,omitempty"` + + // Filter is the ActiveDirectory search filter which should be applied when searching for groups for a user. + // The pattern "{}" must occur in the filter at least once and will be dynamically replaced by the + // dn (distinguished name) of the user entry found as a result of the user search. E.g. "member={}" or + // "&(objectClass=groupOfNames)(member={})". For more information about ActiveDirectory filters, see + // https://ldap.com/ldap-filters. + // Note that the dn (distinguished name) is not an attribute of an entry, so "dn={}" cannot be used. + // Optional. When not specified, the default will act as if the Filter were specified as "member={}". + // +optional + Filter string `json:"filter,omitempty"` + + // Attributes specifies how the group's information should be read from each ActiveDirectory entry which was found as + // the result of the group search. + // +optional + Attributes ActiveDirectoryIdentityProviderGroupSearchAttributes `json:"attributes,omitempty"` +} + +// Spec for configuring an ActiveDirectory identity provider. +type ActiveDirectoryIdentityProviderSpec struct { + // Host is the hostname of this Active Directory identity provider, i.e., where to connect. For example: ldap.example.com:636. + // +kubebuilder:validation:MinLength=1 + Host string `json:"host"` + + // TLS contains the connection settings for how to establish the connection to the Host. + TLS *TLSSpec `json:"tls,omitempty"` + + // Bind contains the configuration for how to provide access credentials during an initial bind to the ActiveDirectory server + // to be allowed to perform searches and binds to validate a user's credentials during a user's authentication attempt. + Bind ActiveDirectoryIdentityProviderBind `json:"bind,omitempty"` + + // UserSearch contains the configuration for searching for a user by name in Active Directory. + UserSearch ActiveDirectoryIdentityProviderUserSearch `json:"userSearch,omitempty"` + + // GroupSearch contains the configuration for searching for a user's group membership in ActiveDirectory. + GroupSearch ActiveDirectoryIdentityProviderGroupSearch `json:"groupSearch,omitempty"` +} + +// ActiveDirectoryIdentityProvider describes the configuration of an upstream Microsoft Active Directory identity provider. +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:categories=pinniped;pinniped-idp;pinniped-idps +// +kubebuilder:printcolumn:name="Host",type=string,JSONPath=`.spec.host` +// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:subresource:status +type ActiveDirectoryIdentityProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec for configuring the identity provider. + Spec ActiveDirectoryIdentityProviderSpec `json:"spec"` + + // Status of the identity provider. + Status ActiveDirectoryIdentityProviderStatus `json:"status,omitempty"` +} + +// List of ActiveDirectoryIdentityProvider objects. +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type ActiveDirectoryIdentityProviderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + Items []ActiveDirectoryIdentityProvider `json:"items"` +} diff --git a/generated/latest/apis/supervisor/idp/v1alpha1/types_meta.go b/generated/latest/apis/supervisor/idp/v1alpha1/types_meta.go index e59976ff..e04c6f2a 100644 --- a/generated/latest/apis/supervisor/idp/v1alpha1/types_meta.go +++ b/generated/latest/apis/supervisor/idp/v1alpha1/types_meta.go @@ -1,4 +1,4 @@ -// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package v1alpha1 diff --git a/generated/latest/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go b/generated/latest/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go index f7762b09..9895a76e 100644 --- a/generated/latest/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go +++ b/generated/latest/apis/supervisor/idp/v1alpha1/zz_generated.deepcopy.go @@ -11,6 +11,196 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProvider) DeepCopyInto(out *ActiveDirectoryIdentityProvider) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProvider. +func (in *ActiveDirectoryIdentityProvider) DeepCopy() *ActiveDirectoryIdentityProvider { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProvider) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopyInto(out *ActiveDirectoryIdentityProviderBind) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderBind. +func (in *ActiveDirectoryIdentityProviderBind) DeepCopy() *ActiveDirectoryIdentityProviderBind { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderBind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearch. +func (in *ActiveDirectoryIdentityProviderGroupSearch) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderGroupSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderGroupSearchAttributes. +func (in *ActiveDirectoryIdentityProviderGroupSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderGroupSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderGroupSearchAttributes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyInto(out *ActiveDirectoryIdentityProviderList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ActiveDirectoryIdentityProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderList. +func (in *ActiveDirectoryIdentityProviderList) DeepCopy() *ActiveDirectoryIdentityProviderList { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ActiveDirectoryIdentityProviderList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopyInto(out *ActiveDirectoryIdentityProviderSpec) { + *out = *in + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLSSpec) + **out = **in + } + out.Bind = in.Bind + out.UserSearch = in.UserSearch + out.GroupSearch = in.GroupSearch + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderSpec. +func (in *ActiveDirectoryIdentityProviderSpec) DeepCopy() *ActiveDirectoryIdentityProviderSpec { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopyInto(out *ActiveDirectoryIdentityProviderStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderStatus. +func (in *ActiveDirectoryIdentityProviderStatus) DeepCopy() *ActiveDirectoryIdentityProviderStatus { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearch) { + *out = *in + out.Attributes = in.Attributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearch. +func (in *ActiveDirectoryIdentityProviderUserSearch) DeepCopy() *ActiveDirectoryIdentityProviderUserSearch { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopyInto(out *ActiveDirectoryIdentityProviderUserSearchAttributes) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveDirectoryIdentityProviderUserSearchAttributes. +func (in *ActiveDirectoryIdentityProviderUserSearchAttributes) DeepCopy() *ActiveDirectoryIdentityProviderUserSearchAttributes { + if in == nil { + return nil + } + out := new(ActiveDirectoryIdentityProviderUserSearchAttributes) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Condition) DeepCopyInto(out *Condition) { *out = *in diff --git a/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..40990cd9 --- /dev/null +++ b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,182 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1" + scheme "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ActiveDirectoryIdentityProvidersGetter has a method to return a ActiveDirectoryIdentityProviderInterface. +// A group's client should implement this interface. +type ActiveDirectoryIdentityProvidersGetter interface { + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface +} + +// ActiveDirectoryIdentityProviderInterface has methods to work with ActiveDirectoryIdentityProvider resources. +type ActiveDirectoryIdentityProviderInterface interface { + Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ActiveDirectoryIdentityProviderList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) + ActiveDirectoryIdentityProviderExpansion +} + +// activeDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type activeDirectoryIdentityProviders struct { + client rest.Interface + ns string +} + +// newActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviders +func newActiveDirectoryIdentityProviders(c *IDPV1alpha1Client, namespace string) *activeDirectoryIdentityProviders { + return &activeDirectoryIdentityProviders{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *activeDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *activeDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ActiveDirectoryIdentityProviderList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *activeDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Post(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *activeDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *activeDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Put(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(activeDirectoryIdentityProvider.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(activeDirectoryIdentityProvider). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *activeDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *activeDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *activeDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + result = &v1alpha1.ActiveDirectoryIdentityProvider{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("activedirectoryidentityproviders"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go new file mode 100644 index 00000000..d8e88b4d --- /dev/null +++ b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_activedirectoryidentityprovider.go @@ -0,0 +1,129 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeActiveDirectoryIdentityProviders implements ActiveDirectoryIdentityProviderInterface +type FakeActiveDirectoryIdentityProviders struct { + Fake *FakeIDPV1alpha1 + ns string +} + +var activedirectoryidentityprovidersResource = schema.GroupVersionResource{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Resource: "activedirectoryidentityproviders"} + +var activedirectoryidentityprovidersKind = schema.GroupVersionKind{Group: "idp.supervisor.pinniped.dev", Version: "v1alpha1", Kind: "ActiveDirectoryIdentityProvider"} + +// Get takes name of the activeDirectoryIdentityProvider, and returns the corresponding activeDirectoryIdentityProvider object, and an error if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// List takes label and field selectors, and returns the list of ActiveDirectoryIdentityProviders that match those selectors. +func (c *FakeActiveDirectoryIdentityProviders) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ActiveDirectoryIdentityProviderList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(activedirectoryidentityprovidersResource, activedirectoryidentityprovidersKind, c.ns, opts), &v1alpha1.ActiveDirectoryIdentityProviderList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ActiveDirectoryIdentityProviderList{ListMeta: obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).ListMeta} + for _, item := range obj.(*v1alpha1.ActiveDirectoryIdentityProviderList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested activeDirectoryIdentityProviders. +func (c *FakeActiveDirectoryIdentityProviders) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(activedirectoryidentityprovidersResource, c.ns, opts)) + +} + +// Create takes the representation of a activeDirectoryIdentityProvider and creates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Create(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.CreateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Update takes the representation of a activeDirectoryIdentityProvider and updates it. Returns the server's representation of the activeDirectoryIdentityProvider, and an error, if there is any. +func (c *FakeActiveDirectoryIdentityProviders) Update(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(activedirectoryidentityprovidersResource, c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeActiveDirectoryIdentityProviders) UpdateStatus(ctx context.Context, activeDirectoryIdentityProvider *v1alpha1.ActiveDirectoryIdentityProvider, opts v1.UpdateOptions) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(activedirectoryidentityprovidersResource, "status", c.ns, activeDirectoryIdentityProvider), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} + +// Delete takes name of the activeDirectoryIdentityProvider and deletes it. Returns an error if one occurs. +func (c *FakeActiveDirectoryIdentityProviders) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(activedirectoryidentityprovidersResource, c.ns, name), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeActiveDirectoryIdentityProviders) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(activedirectoryidentityprovidersResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ActiveDirectoryIdentityProviderList{}) + return err +} + +// Patch applies the patch and returns the patched activeDirectoryIdentityProvider. +func (c *FakeActiveDirectoryIdentityProviders) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ActiveDirectoryIdentityProvider, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(activedirectoryidentityprovidersResource, c.ns, name, pt, data, subresources...), &v1alpha1.ActiveDirectoryIdentityProvider{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), err +} diff --git a/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go index c06f7429..c089ba8b 100644 --- a/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go +++ b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/fake/fake_idp_client.go @@ -15,6 +15,10 @@ type FakeIDPV1alpha1 struct { *testing.Fake } +func (c *FakeIDPV1alpha1) ActiveDirectoryIdentityProviders(namespace string) v1alpha1.ActiveDirectoryIdentityProviderInterface { + return &FakeActiveDirectoryIdentityProviders{c, namespace} +} + func (c *FakeIDPV1alpha1) LDAPIdentityProviders(namespace string) v1alpha1.LDAPIdentityProviderInterface { return &FakeLDAPIdentityProviders{c, namespace} } diff --git a/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go index 137892f3..a7fdb511 100644 --- a/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go +++ b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/generated_expansion.go @@ -5,6 +5,8 @@ package v1alpha1 +type ActiveDirectoryIdentityProviderExpansion interface{} + type LDAPIdentityProviderExpansion interface{} type OIDCIdentityProviderExpansion interface{} diff --git a/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go index a32a2dd1..f492b7e6 100644 --- a/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go +++ b/generated/latest/client/supervisor/clientset/versioned/typed/idp/v1alpha1/idp_client.go @@ -13,6 +13,7 @@ import ( type IDPV1alpha1Interface interface { RESTClient() rest.Interface + ActiveDirectoryIdentityProvidersGetter LDAPIdentityProvidersGetter OIDCIdentityProvidersGetter } @@ -22,6 +23,10 @@ type IDPV1alpha1Client struct { restClient rest.Interface } +func (c *IDPV1alpha1Client) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderInterface { + return newActiveDirectoryIdentityProviders(c, namespace) +} + func (c *IDPV1alpha1Client) LDAPIdentityProviders(namespace string) LDAPIdentityProviderInterface { return newLDAPIdentityProviders(c, namespace) } diff --git a/generated/latest/client/supervisor/informers/externalversions/generic.go b/generated/latest/client/supervisor/informers/externalversions/generic.go index 338a4d72..6c6b427d 100644 --- a/generated/latest/client/supervisor/informers/externalversions/generic.go +++ b/generated/latest/client/supervisor/informers/externalversions/generic.go @@ -45,6 +45,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Config().V1alpha1().FederationDomains().Informer()}, nil // Group=idp.supervisor.pinniped.dev, Version=v1alpha1 + case idpv1alpha1.SchemeGroupVersion.WithResource("activedirectoryidentityproviders"): + return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().ActiveDirectoryIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("ldapidentityproviders"): return &genericInformer{resource: resource.GroupResource(), informer: f.IDP().V1alpha1().LDAPIdentityProviders().Informer()}, nil case idpv1alpha1.SchemeGroupVersion.WithResource("oidcidentityproviders"): diff --git a/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..d0393f4e --- /dev/null +++ b/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,77 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + idpv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1" + versioned "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned" + internalinterfaces "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions/internalinterfaces" + v1alpha1 "go.pinniped.dev/generated/latest/client/supervisor/listers/idp/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderInformer provides access to a shared informer and lister for +// ActiveDirectoryIdentityProviders. +type ActiveDirectoryIdentityProviderInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ActiveDirectoryIdentityProviderLister +} + +type activeDirectoryIdentityProviderInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredActiveDirectoryIdentityProviderInformer constructs a new informer for ActiveDirectoryIdentityProvider type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredActiveDirectoryIdentityProviderInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.IDPV1alpha1().ActiveDirectoryIdentityProviders(namespace).Watch(context.TODO(), options) + }, + }, + &idpv1alpha1.ActiveDirectoryIdentityProvider{}, + resyncPeriod, + indexers, + ) +} + +func (f *activeDirectoryIdentityProviderInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredActiveDirectoryIdentityProviderInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *activeDirectoryIdentityProviderInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&idpv1alpha1.ActiveDirectoryIdentityProvider{}, f.defaultInformer) +} + +func (f *activeDirectoryIdentityProviderInformer) Lister() v1alpha1.ActiveDirectoryIdentityProviderLister { + return v1alpha1.NewActiveDirectoryIdentityProviderLister(f.Informer().GetIndexer()) +} diff --git a/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go b/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go index 1a1c2d57..4f19f336 100644 --- a/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go +++ b/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1/interface.go @@ -11,6 +11,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. + ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. LDAPIdentityProviders() LDAPIdentityProviderInformer // OIDCIdentityProviders returns a OIDCIdentityProviderInformer. @@ -28,6 +30,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// ActiveDirectoryIdentityProviders returns a ActiveDirectoryIdentityProviderInformer. +func (v *version) ActiveDirectoryIdentityProviders() ActiveDirectoryIdentityProviderInformer { + return &activeDirectoryIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // LDAPIdentityProviders returns a LDAPIdentityProviderInformer. func (v *version) LDAPIdentityProviders() LDAPIdentityProviderInformer { return &lDAPIdentityProviderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/generated/latest/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go b/generated/latest/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go new file mode 100644 index 00000000..47c573cc --- /dev/null +++ b/generated/latest/client/supervisor/listers/idp/v1alpha1/activedirectoryidentityprovider.go @@ -0,0 +1,86 @@ +// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ActiveDirectoryIdentityProviderLister helps list ActiveDirectoryIdentityProviders. +// All objects returned here must be treated as read-only. +type ActiveDirectoryIdentityProviderLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. + ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister + ActiveDirectoryIdentityProviderListerExpansion +} + +// activeDirectoryIdentityProviderLister implements the ActiveDirectoryIdentityProviderLister interface. +type activeDirectoryIdentityProviderLister struct { + indexer cache.Indexer +} + +// NewActiveDirectoryIdentityProviderLister returns a new ActiveDirectoryIdentityProviderLister. +func NewActiveDirectoryIdentityProviderLister(indexer cache.Indexer) ActiveDirectoryIdentityProviderLister { + return &activeDirectoryIdentityProviderLister{indexer: indexer} +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer. +func (s *activeDirectoryIdentityProviderLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// ActiveDirectoryIdentityProviders returns an object that can list and get ActiveDirectoryIdentityProviders. +func (s *activeDirectoryIdentityProviderLister) ActiveDirectoryIdentityProviders(namespace string) ActiveDirectoryIdentityProviderNamespaceLister { + return activeDirectoryIdentityProviderNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ActiveDirectoryIdentityProviderNamespaceLister helps list and get ActiveDirectoryIdentityProviders. +// All objects returned here must be treated as read-only. +type ActiveDirectoryIdentityProviderNamespaceLister interface { + // List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) + // Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) + ActiveDirectoryIdentityProviderNamespaceListerExpansion +} + +// activeDirectoryIdentityProviderNamespaceLister implements the ActiveDirectoryIdentityProviderNamespaceLister +// interface. +type activeDirectoryIdentityProviderNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ActiveDirectoryIdentityProviders in the indexer for a given namespace. +func (s activeDirectoryIdentityProviderNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ActiveDirectoryIdentityProvider, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ActiveDirectoryIdentityProvider)) + }) + return ret, err +} + +// Get retrieves the ActiveDirectoryIdentityProvider from the indexer for a given namespace and name. +func (s activeDirectoryIdentityProviderNamespaceLister) Get(name string) (*v1alpha1.ActiveDirectoryIdentityProvider, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("activedirectoryidentityprovider"), name) + } + return obj.(*v1alpha1.ActiveDirectoryIdentityProvider), nil +} diff --git a/generated/latest/client/supervisor/listers/idp/v1alpha1/expansion_generated.go b/generated/latest/client/supervisor/listers/idp/v1alpha1/expansion_generated.go index 28f41bd7..7c625e80 100644 --- a/generated/latest/client/supervisor/listers/idp/v1alpha1/expansion_generated.go +++ b/generated/latest/client/supervisor/listers/idp/v1alpha1/expansion_generated.go @@ -5,6 +5,14 @@ package v1alpha1 +// ActiveDirectoryIdentityProviderListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderLister. +type ActiveDirectoryIdentityProviderListerExpansion interface{} + +// ActiveDirectoryIdentityProviderNamespaceListerExpansion allows custom methods to be added to +// ActiveDirectoryIdentityProviderNamespaceLister. +type ActiveDirectoryIdentityProviderNamespaceListerExpansion interface{} + // LDAPIdentityProviderListerExpansion allows custom methods to be added to // LDAPIdentityProviderLister. type LDAPIdentityProviderListerExpansion interface{} diff --git a/go.mod b/go.mod index 584c25a5..7c91fc2e 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/go-logr/stdr v0.4.0 github.com/go-openapi/spec v0.20.3 // indirect github.com/gofrs/flock v0.8.1 + github.com/gofrs/uuid v3.2.0+incompatible github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.5.6 github.com/google/gofuzz v1.2.0 diff --git a/go.sum b/go.sum index 6c545de3..fce7b442 100644 --- a/go.sum +++ b/go.sum @@ -554,6 +554,7 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid/v3 v3.1.2/go.mod h1:xPwMqoocQ1L5G6pXX5BcE7N5jlzn2o19oqAKxwZW/kI= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= diff --git a/internal/upstreamad/upstreamad.go b/internal/upstreamad/upstreamad.go new file mode 100644 index 00000000..eff0a9f9 --- /dev/null +++ b/internal/upstreamad/upstreamad.go @@ -0,0 +1,654 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package upstreamad implements an active directory specific abstraction of upstream LDAP IDP interactions. +package upstreamad + +import ( + "context" + "crypto/tls" + "crypto/x509" + "encoding/base64" + "errors" + "fmt" + "net" + "net/url" + "sort" + "strings" + "time" + + "github.com/go-ldap/ldap/v3" + "github.com/gofrs/uuid" + "k8s.io/apiserver/pkg/authentication/authenticator" + "k8s.io/apiserver/pkg/authentication/user" + "k8s.io/utils/trace" + + "go.pinniped.dev/internal/authenticators" + "go.pinniped.dev/internal/endpointaddr" + "go.pinniped.dev/internal/oidc/provider" + "go.pinniped.dev/internal/plog" +) + +const ( + ldapsScheme = "ldaps" + distinguishedNameAttributeName = "dn" + objectGUIDAttributeName = "objectGUID" + sAMAccountNameAttributeName = "sAMAccountName" + searchFilterInterpolationLocationMarker = "{}" + groupSearchPageSize = uint32(250) + defaultLDAPPort = uint16(389) + defaultLDAPSPort = uint16(636) +) + +// Conn abstracts the upstream LDAP communication protocol (mostly for testing). +type Conn interface { + Bind(username, password string) error + + Search(searchRequest *ldap.SearchRequest) (*ldap.SearchResult, error) + + SearchWithPaging(searchRequest *ldap.SearchRequest, pagingSize uint32) (*ldap.SearchResult, error) + + Close() +} + +// Our Conn type is subset of the ldap.Client interface, which is implemented by ldap.Conn. +var _ Conn = &ldap.Conn{} + +// LDAPDialer is a factory of Conn, and the resulting Conn can then be used to interact with an upstream LDAP IDP. +type LDAPDialer interface { + Dial(ctx context.Context, addr endpointaddr.HostPort) (Conn, error) +} + +// LDAPDialerFunc makes it easy to use a func as an LDAPDialer. +type LDAPDialerFunc func(ctx context.Context, addr endpointaddr.HostPort) (Conn, error) + +var _ LDAPDialer = LDAPDialerFunc(nil) + +func (f LDAPDialerFunc) Dial(ctx context.Context, addr endpointaddr.HostPort) (Conn, error) { + return f(ctx, addr) +} + +type LDAPConnectionProtocol string + +const ( + StartTLS = LDAPConnectionProtocol("StartTLS") + TLS = LDAPConnectionProtocol("TLS") +) + +// ProviderConfig includes all of the settings for connection and searching for users and groups in +// the upstream LDAP IDP. It also provides methods for testing the connection and performing logins. +// The nested structs are not pointer fields to enable deep copy on function params and return values. +type ProviderConfig struct { + // Name is the unique name of this upstream LDAP IDP. + Name string + + // Host is the hostname or "hostname:port" of the LDAP server. When the port is not specified, + // the default LDAP port will be used. + Host string + + // ConnectionProtocol determines how to establish the connection to the server. Either StartTLS or TLS. + ConnectionProtocol LDAPConnectionProtocol + + // PEM-encoded CA cert bundle to trust when connecting to the LDAP server. Can be nil. + CABundle []byte + + // BindUsername is the username to use when performing a bind with the upstream active directory IDP. + BindUsername string + + // BindPassword is the password to use when performing a bind with the upstream active directory IDP. + BindPassword string + + // UserSearch contains information about how to search for users in the upstream active directory IDP. + UserSearch UserSearchConfig + + // GroupSearch contains information about how to search for group membership in the upstream active directory IDP. + GroupSearch GroupSearchConfig + + // Dialer exists to enable testing. When nil, will use a default appropriate for production use. + Dialer LDAPDialer +} + +// UserSearchConfig contains information about how to search for users in the upstream active directory IDP. +type UserSearchConfig struct { + // Base is the base DN to use for the user search in the upstream active directory IDP. + Base string + + // Filter is the filter to use for the user search in the upstream active directory IDP. + Filter string + + // UsernameAttribute is the attribute in the LDAP entry from which the username should be + // retrieved. Empty means to use 'sAMAccountName'. + UsernameAttribute string + + // UIDAttribute is the attribute in the LDAP entry from which the user's unique ID should be + // retrieved. Empty means to use 'objectGUID'. + UIDAttribute string +} + +// GroupSearchConfig contains information about how to search for group membership for users in the upstream active directory IDP. +type GroupSearchConfig struct { + // Base is the base DN to use for the group search in the upstream active directory IDP. Empty means to skip group search + // entirely, in which case authenticated users will not belong to any groups from the upstream active directory IDP. + Base string + + // Filter is the filter to use for the group search in the upstream active directory IDP. Empty means to use `member={}`. + Filter string + + // GroupNameAttribute is the attribute in the LDAP group entry from which the group name should be + // retrieved. Empty means to use 'cn'. + GroupNameAttribute string +} + +type Provider struct { + c ProviderConfig +} + +var _ provider.UpstreamLDAPIdentityProviderI = &Provider{} +var _ authenticators.UserAuthenticator = &Provider{} + +// Create a Provider. The config is not a pointer to ensure that a copy of the config is created, +// making the resulting Provider use an effectively read-only configuration. +func New(config ProviderConfig) *Provider { + return &Provider{c: config} +} + +// A reader for the config. Returns a copy of the config to keep the underlying config read-only. +func (p *Provider) GetConfig() ProviderConfig { + return p.c +} + +func (p *Provider) dial(ctx context.Context) (Conn, error) { + tlsAddr, err := endpointaddr.Parse(p.c.Host, defaultLDAPSPort) + if err != nil { + return nil, ldap.NewError(ldap.ErrorNetwork, err) + } + + startTLSAddr, err := endpointaddr.Parse(p.c.Host, defaultLDAPPort) + if err != nil { + return nil, ldap.NewError(ldap.ErrorNetwork, err) + } + + // Choose how and where to dial based on TLS vs. StartTLS config option. + var dialFunc LDAPDialerFunc + var addr endpointaddr.HostPort + switch { + case p.c.ConnectionProtocol == TLS: + dialFunc = p.dialTLS + addr = tlsAddr + case p.c.ConnectionProtocol == StartTLS: + dialFunc = p.dialStartTLS + addr = startTLSAddr + default: + return nil, ldap.NewError(ldap.ErrorNetwork, fmt.Errorf("did not specify valid ConnectionProtocol")) + } + + // Override the real dialer for testing purposes sometimes. + if p.c.Dialer != nil { + dialFunc = p.c.Dialer.Dial + } + + return dialFunc(ctx, addr) +} + +// dialTLS is a default implementation of the Dialer, used when Dialer is nil and ConnectionProtocol is TLS. +// Unfortunately, the go-ldap library does not seem to support dialing with a context.Context, +// so we implement it ourselves, heavily inspired by ldap.DialURL. +func (p *Provider) dialTLS(ctx context.Context, addr endpointaddr.HostPort) (Conn, error) { + tlsConfig, err := p.tlsConfig() + if err != nil { + return nil, ldap.NewError(ldap.ErrorNetwork, err) + } + + dialer := &tls.Dialer{NetDialer: netDialer(), Config: tlsConfig} + c, err := dialer.DialContext(ctx, "tcp", addr.Endpoint()) + if err != nil { + return nil, ldap.NewError(ldap.ErrorNetwork, err) + } + + conn := ldap.NewConn(c, true) + conn.Start() + return conn, nil +} + +// dialTLS is a default implementation of the Dialer, used when Dialer is nil and ConnectionProtocol is StartTLS. +// Unfortunately, the go-ldap library does not seem to support dialing with a context.Context, +// so we implement it ourselves, heavily inspired by ldap.DialURL. +func (p *Provider) dialStartTLS(ctx context.Context, addr endpointaddr.HostPort) (Conn, error) { + tlsConfig, err := p.tlsConfig() + if err != nil { + return nil, ldap.NewError(ldap.ErrorNetwork, err) + } + + // Unfortunately, this seems to be required for StartTLS, even though it is not needed for regular TLS. + tlsConfig.ServerName = addr.Host + + c, err := netDialer().DialContext(ctx, "tcp", addr.Endpoint()) + if err != nil { + return nil, ldap.NewError(ldap.ErrorNetwork, err) + } + + conn := ldap.NewConn(c, false) + conn.Start() + err = conn.StartTLS(tlsConfig) + if err != nil { + return nil, err + } + + return conn, nil +} + +func netDialer() *net.Dialer { + return &net.Dialer{Timeout: time.Minute} +} + +func (p *Provider) tlsConfig() (*tls.Config, error) { + var rootCAs *x509.CertPool + if p.c.CABundle != nil { + rootCAs = x509.NewCertPool() + if !rootCAs.AppendCertsFromPEM(p.c.CABundle) { + return nil, fmt.Errorf("could not parse CA bundle") + } + } + return &tls.Config{MinVersion: tls.VersionTLS12, RootCAs: rootCAs}, nil +} + +// A name for this upstream provider. +func (p *Provider) GetName() string { + return p.c.Name +} + +// Return a URL which uniquely identifies this LDAP provider, e.g. "ldaps://host.example.com:1234?base=user-search-base". +// This URL is not used for connecting to the provider, but rather is used for creating a globally unique user +// identifier by being combined with the user's UID, since user UIDs are only unique within one provider. +func (p *Provider) GetURL() *url.URL { + u := &url.URL{Scheme: ldapsScheme, Host: p.c.Host} + q := u.Query() + q.Set("base", p.c.UserSearch.Base) + u.RawQuery = q.Encode() + return u +} + +// TestConnection provides a method for testing the connection and bind settings. It performs a dial and bind +// and returns any errors that we encountered. +func (p *Provider) TestConnection(ctx context.Context) error { + err := p.validateConfig() + if err != nil { + return err + } + + conn, err := p.dial(ctx) + if err != nil { + return fmt.Errorf(`error dialing host "%s": %w`, p.c.Host, err) + } + defer conn.Close() + + err = conn.Bind(p.c.BindUsername, p.c.BindPassword) + if err != nil { + return fmt.Errorf(`error binding as "%s": %w`, p.c.BindUsername, err) + } + + return nil +} + +// DryRunAuthenticateUser provides a method for testing all of the Provider settings in a kind of dry run of +// authentication for a given end user's username. It runs the same logic as AuthenticateUser except it does +// not bind as that user, so it does not test their password. It returns the same values that a real call to +// AuthenticateUser with the correct password would return. +func (p *Provider) DryRunAuthenticateUser(ctx context.Context, username string) (*authenticator.Response, bool, error) { + endUserBindFunc := func(conn Conn, foundUserDN string) error { + // Act as if the end user bind always succeeds. + return nil + } + return p.authenticateUserImpl(ctx, username, endUserBindFunc) +} + +// Authenticate an end user and return their mapped username, groups, and UID. Implements authenticators.UserAuthenticator. +func (p *Provider) AuthenticateUser(ctx context.Context, username, password string) (*authenticator.Response, bool, error) { + endUserBindFunc := func(conn Conn, foundUserDN string) error { + return conn.Bind(foundUserDN, password) + } + return p.authenticateUserImpl(ctx, username, endUserBindFunc) +} + +func (p *Provider) authenticateUserImpl(ctx context.Context, username string, bindFunc func(conn Conn, foundUserDN string) error) (*authenticator.Response, bool, error) { + t := trace.FromContext(ctx).Nest("slow ldap authenticate user attempt", trace.Field{Key: "providerName", Value: p.GetName()}) + defer t.LogIfLong(500 * time.Millisecond) // to help users debug slow LDAP searches + + err := p.validateConfig() + if err != nil { + p.traceAuthFailure(t, err) + return nil, false, err + } + + if len(username) == 0 { + // Empty passwords are already handled by go-ldap. + p.traceAuthFailure(t, fmt.Errorf("empty username")) + return nil, false, nil + } + + conn, err := p.dial(ctx) + if err != nil { + p.traceAuthFailure(t, err) + return nil, false, fmt.Errorf(`error dialing host "%s": %w`, p.c.Host, err) + } + defer conn.Close() + + err = conn.Bind(p.c.BindUsername, p.c.BindPassword) + if err != nil { + p.traceAuthFailure(t, err) + return nil, false, fmt.Errorf(`error binding as "%s" before user search: %w`, p.c.BindUsername, err) + } + + mappedUsername, mappedUID, mappedGroupNames, err := p.searchAndBindUser(conn, username, bindFunc) + if err != nil { + p.traceAuthFailure(t, err) + return nil, false, err + } + if len(mappedUsername) == 0 || len(mappedUID) == 0 { + // Couldn't find the username or couldn't bind using the password. + p.traceAuthFailure(t, fmt.Errorf("bad username or password")) + return nil, false, nil + } + + response := &authenticator.Response{ + User: &user.DefaultInfo{ + Name: mappedUsername, + UID: mappedUID, + Groups: mappedGroupNames, + }, + } + p.traceAuthSuccess(t) + return response, true, nil +} + +func (p *Provider) searchGroupsForUserDN(conn Conn, userDN string) ([]string, error) { + searchResult, err := conn.SearchWithPaging(p.groupSearchRequest(userDN), groupSearchPageSize) + if err != nil { + return nil, fmt.Errorf(`error searching for group memberships for user with DN %q: %w`, userDN, err) + } + + groupAttributeName := p.c.GroupSearch.GroupNameAttribute + if len(groupAttributeName) == 0 { + groupAttributeName = distinguishedNameAttributeName + } + + groups := []string{} + for _, groupEntry := range searchResult.Entries { + if len(groupEntry.DN) == 0 { + return nil, fmt.Errorf(`searching for group memberships for user with DN %q resulted in search result without DN`, userDN) + } + mappedGroupName, err := p.getSearchResultAttributeValue(groupAttributeName, groupEntry, userDN) + if err != nil { + return nil, fmt.Errorf(`error searching for group memberships for user with DN %q: %w`, userDN, err) + } + groups = append(groups, mappedGroupName) + } + + return groups, nil +} + +func (p *Provider) validateConfig() error { + // TODO if user search base is nil then host must be an IP address? + if p.usernameAttribute() == distinguishedNameAttributeName && len(p.c.UserSearch.Filter) == 0 { + // LDAP search filters do not allow searching by DN, so we would have no reasonable default for Filter. + return fmt.Errorf(`must specify UserSearch Filter when UserSearch UsernameAttribute is "dn"`) + } + return nil +} + +func (p *Provider) searchAndBindUser(conn Conn, username string, bindFunc func(conn Conn, foundUserDN string) error) (string, string, []string, error) { + searchResult, err := conn.Search(p.userSearchRequest(username)) + if err != nil { + plog.All(`error searching for user`, + "upstreamName", p.GetName(), + "username", username, + "err", err, + ) + return "", "", nil, fmt.Errorf(`error searching for user: %w`, err) + } + if len(searchResult.Entries) == 0 { + if plog.Enabled(plog.LevelAll) { + plog.All("error finding user: user not found (if this username is valid, please check the user search configuration)", + "upstreamName", p.GetName(), + "username", username, + ) + } else { + plog.Debug("error finding user: user not found (cowardly avoiding printing username because log level is not 'all')", "upstreamName", p.GetName()) + } + return "", "", nil, nil + } + + // At this point, we have matched at least one entry, so we can be confident that the username is not actually + // someone's password mistakenly entered into the username field, so we can log it without concern. + if len(searchResult.Entries) > 1 { + return "", "", nil, fmt.Errorf(`searching for user "%s" resulted in %d search results, but expected 1 result`, + username, len(searchResult.Entries), + ) + } + userEntry := searchResult.Entries[0] + if len(userEntry.DN) == 0 { + return "", "", nil, fmt.Errorf(`searching for user "%s" resulted in search result without DN`, username) + } + + mappedUsername, err := p.getSearchResultAttributeValue(p.usernameAttribute(), userEntry, username) + if err != nil { + return "", "", nil, err + } + + // We would like to support binary typed attributes for UIDs, so always read them as binary and encode them, + // even when the attribute may not be binary. + mappedUID, err := p.getSearchResultAttributeRawValueEncoded(p.uidAttribute(), userEntry, username) + if err != nil { + return "", "", nil, err + } + + mappedGroupNames := []string{} + if len(p.c.GroupSearch.Base) > 0 { + mappedGroupNames, err = p.searchGroupsForUserDN(conn, userEntry.DN) + if err != nil { + return "", "", nil, err + } + } + sort.Strings(mappedGroupNames) + + // Caution: Note that any other LDAP commands after this bind will be run as this user instead of as the configured BindUsername! + err = bindFunc(conn, userEntry.DN) + if err != nil { + plog.DebugErr("error binding for user (if this is not the expected dn for this username, please check the user search configuration)", + err, "upstreamName", p.GetName(), "username", username, "dn", userEntry.DN) + ldapErr := &ldap.Error{} + if errors.As(err, &ldapErr) && ldapErr.ResultCode == ldap.LDAPResultInvalidCredentials { + return "", "", nil, nil + } + return "", "", nil, fmt.Errorf(`error binding for user "%s" using provided password against DN "%s": %w`, username, userEntry.DN, err) + } + + return mappedUsername, mappedUID, mappedGroupNames, nil +} + +func (p *Provider) userSearchRequest(username string) *ldap.SearchRequest { + // See https://ldap.com/the-ldap-search-operation for general documentation of LDAP search options. + return &ldap.SearchRequest{ + BaseDN: p.userSearchBase(), + Scope: ldap.ScopeWholeSubtree, + DerefAliases: ldap.NeverDerefAliases, + SizeLimit: 2, + TimeLimit: 90, + TypesOnly: false, + Filter: p.userSearchFilter(username), + Attributes: p.userSearchRequestedAttributes(), + Controls: nil, // this could be used to enable paging, but we're already limiting the result max size + } +} + +func (p *Provider) userSearchBase() string { + if len(p.c.UserSearch.Base) == 0 { + parsed, err := endpointaddr.Parse(p.c.Host, 636) + if err != nil { + return "" + } + dcParts := strings.Split(parsed.Host, ".") + base := "" + for i, dcPart := range dcParts { + base += "dc=" + dcPart + if i < len(dcParts)-1 { + base += "," + } + } + return base + } + return p.c.UserSearch.Base +} + +func (p *Provider) groupSearchRequest(userDN string) *ldap.SearchRequest { + // See https://ldap.com/the-ldap-search-operation for general documentation of LDAP search options. + return &ldap.SearchRequest{ + BaseDN: p.c.GroupSearch.Base, + Scope: ldap.ScopeWholeSubtree, + DerefAliases: ldap.NeverDerefAliases, + SizeLimit: 0, // unlimited size because we will search with paging + TimeLimit: 90, + TypesOnly: false, + Filter: p.groupSearchFilter(userDN), + Attributes: p.groupSearchRequestedAttributes(), + Controls: nil, // nil because ldap.SearchWithPaging() will set the appropriate controls for us + } +} + +func (p *Provider) userSearchRequestedAttributes() []string { + attributes := []string{} + if p.usernameAttribute() != distinguishedNameAttributeName { + attributes = append(attributes, p.usernameAttribute()) + } + if p.uidAttribute() != distinguishedNameAttributeName { + attributes = append(attributes, p.uidAttribute()) + } + return attributes +} + +func (p *Provider) groupSearchRequestedAttributes() []string { + switch p.c.GroupSearch.GroupNameAttribute { + case "": + return []string{} + case distinguishedNameAttributeName: + return []string{} + default: + return []string{p.c.GroupSearch.GroupNameAttribute} + } +} + +func (p *Provider) usernameAttribute() string { + if len(p.c.UserSearch.UsernameAttribute) == 0 { + return sAMAccountNameAttributeName + } + return p.c.UserSearch.UsernameAttribute +} + +func (p *Provider) uidAttribute() string { + if len(p.c.UserSearch.UIDAttribute) == 0 { + return objectGUIDAttributeName + } + return p.c.UserSearch.UIDAttribute +} + +func (p *Provider) userSearchFilter(username string) string { + safeUsername := p.escapeUsernameForSearchFilter(username) + if len(p.c.UserSearch.Filter) == 0 { + return fmt.Sprintf("(%s=%s)", p.usernameAttribute(), safeUsername) + } + return interpolateSearchFilter(p.c.UserSearch.Filter, safeUsername) +} + +func (p *Provider) groupSearchFilter(userDN string) string { + if len(p.c.GroupSearch.Filter) == 0 { + return fmt.Sprintf("(member=%s)", userDN) + } + return interpolateSearchFilter(p.c.GroupSearch.Filter, userDN) +} + +func interpolateSearchFilter(filterFormat, valueToInterpolateIntoFilter string) string { + filter := strings.ReplaceAll(filterFormat, searchFilterInterpolationLocationMarker, valueToInterpolateIntoFilter) + if strings.HasPrefix(filter, "(") && strings.HasSuffix(filter, ")") { + return filter + } + return "(" + filter + ")" +} + +func (p *Provider) escapeUsernameForSearchFilter(username string) string { + // The username is end user input, so it should be escaped before being included in a search to prevent query injection. + return ldap.EscapeFilter(username) +} + +// Returns the (potentially) binary data of the attribute's value, base64 URL encoded. +func (p *Provider) getSearchResultAttributeRawValueEncoded(attributeName string, entry *ldap.Entry, username string) (string, error) { + if attributeName == distinguishedNameAttributeName { + return base64.RawURLEncoding.EncodeToString([]byte(entry.DN)), nil + } + + attributeValues := entry.GetRawAttributeValues(attributeName) + + if len(attributeValues) != 1 { + return "", fmt.Errorf(`found %d values for attribute "%s" while searching for user "%s", but expected 1 result`, + len(attributeValues), attributeName, username, + ) + } + + attributeValue := attributeValues[0] + if len(attributeValue) == 0 { + return "", fmt.Errorf(`found empty value for attribute "%s" while searching for user "%s", but expected value to be non-empty`, + attributeName, username, + ) + } + + if attributeName == objectGUIDAttributeName { + // In AD, objectGUID will be represented as a base64-encoded UUID. Convert it back to UUID encoding. + base64decoded, err := base64.StdEncoding.DecodeString(entry.GetAttributeValue(attributeName)) + if err != nil { + // TODO if there is an error, should we throw it or pass it through as base64? + return "", fmt.Errorf("Error decoding UID: %s", err.Error()) + } + uuidEntry, err := uuid.FromBytes(base64decoded) + if err != nil { + return "", fmt.Errorf("Error decoding UID: %s", err.Error()) + } + return uuidEntry.String(), nil + } + + return base64.RawURLEncoding.EncodeToString(attributeValue), nil +} + +func (p *Provider) getSearchResultAttributeValue(attributeName string, entry *ldap.Entry, username string) (string, error) { + if attributeName == distinguishedNameAttributeName { + return entry.DN, nil + } + + attributeValues := entry.GetAttributeValues(attributeName) + + if len(attributeValues) != 1 { + return "", fmt.Errorf(`found %d values for attribute "%s" while searching for user "%s", but expected 1 result`, + len(attributeValues), attributeName, username, + ) + } + + attributeValue := attributeValues[0] + if len(attributeValue) == 0 { + return "", fmt.Errorf(`found empty value for attribute "%s" while searching for user "%s", but expected value to be non-empty`, + attributeName, username, + ) + } + + return attributeValue, nil +} + +func (p *Provider) traceAuthFailure(t *trace.Trace, err error) { + t.Step("authentication failed", + trace.Field{Key: "authenticated", Value: false}, + trace.Field{Key: "reason", Value: err.Error()}, + ) +} + +func (p *Provider) traceAuthSuccess(t *trace.Trace) { + t.Step("authentication succeeded", + trace.Field{Key: "authenticated", Value: true}, + ) +} diff --git a/internal/upstreamad/upstreamad_test.go b/internal/upstreamad/upstreamad_test.go new file mode 100644 index 00000000..a518bae2 --- /dev/null +++ b/internal/upstreamad/upstreamad_test.go @@ -0,0 +1,1375 @@ +// Copyright 2021 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package upstreamad + +import ( + "context" + "crypto/tls" + "encoding/base64" + "errors" + "fmt" + "net" + "net/http" + "net/url" + "testing" + "time" + + "github.com/go-ldap/ldap/v3" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "k8s.io/apiserver/pkg/authentication/authenticator" + "k8s.io/apiserver/pkg/authentication/user" + + "go.pinniped.dev/internal/certauthority" + "go.pinniped.dev/internal/endpointaddr" + "go.pinniped.dev/internal/mocks/mockldapconn" + "go.pinniped.dev/internal/testutil" +) + +const ( + testHost = "activedirectory.example.com:8443" + testBindUsername = "cn=some-bind-username,dc=pinniped,dc=dev" + testBindPassword = "some-bind-password" + testUpstreamUsername = "some-upstream-username" + testUpstreamPassword = "some-upstream-password" + testUserSearchBase = "some-upstream-user-base-dn" + testGroupSearchBase = "some-upstream-group-base-dn" + testUserSearchFilter = "some-user-filter={}-and-more-filter={}" + testGroupSearchFilter = "some-group-filter={}-and-more-filter={}" + testUserSearchUsernameAttribute = "some-upstream-username-attribute" + testUserSearchUIDAttribute = "objectGUID" + testGroupSearchGroupNameAttribute = "some-upstream-group-name-attribute" + testUserSearchResultDNValue = "some-upstream-user-dn" + testGroupSearchResultDNValue1 = "some-upstream-group-dn1" + testGroupSearchResultDNValue2 = "some-upstream-group-dn2" + testUserSearchResultUsernameAttributeValue = "some-upstream-username-value" + testUserSearchResultUIDAttributeValue = "Ej5FZ+ibEtOkVkJmFBdAAA==" // this is base64 encoded 123e4567-e89b-12d3-a456-426614174000 + testGroupSearchResultGroupNameAttributeValue1 = "some-upstream-group-name-value1" + testGroupSearchResultGroupNameAttributeValue2 = "some-upstream-group-name-value2" + + expectedGroupSearchPageSize = uint32(250) +) + +var ( + testUserSearchFilterInterpolated = fmt.Sprintf("(some-user-filter=%s-and-more-filter=%s)", testUpstreamUsername, testUpstreamUsername) + testGroupSearchFilterInterpolated = fmt.Sprintf("(some-group-filter=%s-and-more-filter=%s)", testUserSearchResultDNValue, testUserSearchResultDNValue) +) + +func TestEndUserAuthentication(t *testing.T) { + providerConfig := func(editFunc func(p *ProviderConfig)) *ProviderConfig { + config := &ProviderConfig{ + Name: "some-provider-name", + Host: testHost, + CABundle: nil, // this field is only used by the production dialer, which is replaced by a mock for this test + ConnectionProtocol: TLS, + BindUsername: testBindUsername, + BindPassword: testBindPassword, + UserSearch: UserSearchConfig{ + Base: testUserSearchBase, + Filter: testUserSearchFilter, + UsernameAttribute: testUserSearchUsernameAttribute, + UIDAttribute: testUserSearchUIDAttribute, + }, + GroupSearch: GroupSearchConfig{ + Base: testGroupSearchBase, + Filter: testGroupSearchFilter, + GroupNameAttribute: testGroupSearchGroupNameAttribute, + }, + } + if editFunc != nil { + editFunc(config) + } + return config + } + + expectedUserSearch := func(editFunc func(r *ldap.SearchRequest)) *ldap.SearchRequest { + request := &ldap.SearchRequest{ + BaseDN: testUserSearchBase, + Scope: ldap.ScopeWholeSubtree, + DerefAliases: ldap.NeverDerefAliases, + SizeLimit: 2, + TimeLimit: 90, + TypesOnly: false, + Filter: testUserSearchFilterInterpolated, + Attributes: []string{testUserSearchUsernameAttribute, testUserSearchUIDAttribute}, + Controls: nil, // don't need paging because we set the SizeLimit so small + } + if editFunc != nil { + editFunc(request) + } + return request + } + + expectedGroupSearch := func(editFunc func(r *ldap.SearchRequest)) *ldap.SearchRequest { + request := &ldap.SearchRequest{ + BaseDN: testGroupSearchBase, + Scope: ldap.ScopeWholeSubtree, + DerefAliases: ldap.NeverDerefAliases, + SizeLimit: 0, // unlimited size because we will search with paging + TimeLimit: 90, + TypesOnly: false, + Filter: testGroupSearchFilterInterpolated, + Attributes: []string{testGroupSearchGroupNameAttribute}, + Controls: nil, // nil because ldap.SearchWithPaging() will set the appropriate controls for us + } + if editFunc != nil { + editFunc(request) + } + return request + } + + exampleUserSearchResult := &ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUsernameAttribute, []string{testUserSearchResultUsernameAttributeValue}), + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{testUserSearchResultUIDAttributeValue}), + }, + }, + }, + } + + exampleGroupSearchResult := &ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{testGroupSearchResultGroupNameAttributeValue1}), + }, + }, + { + DN: testGroupSearchResultDNValue2, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{testGroupSearchResultGroupNameAttributeValue2}), + }, + }, + }, + Referrals: []string{}, // note that we are not following referrals at this time + Controls: []ldap.Control{}, + } + + // The auth response which matches the exampleUserSearchResult and exampleGroupSearchResult. + expectedAuthResponse := func(editFunc func(r *user.DefaultInfo)) *authenticator.Response { + u := &user.DefaultInfo{ + Name: testUserSearchResultUsernameAttributeValue, + UID: "123e4567-e89b-12d3-a456-426614174000", + Groups: []string{testGroupSearchResultGroupNameAttributeValue1, testGroupSearchResultGroupNameAttributeValue2}, + } + if editFunc != nil { + editFunc(u) + } + return &authenticator.Response{User: u} + } + + tests := []struct { + name string + username string + password string + providerConfig *ProviderConfig + searchMocks func(conn *mockldapconn.MockConn) + bindEndUserMocks func(conn *mockldapconn.MockConn) + dialError error + wantError string + wantToSkipDial bool + wantAuthResponse *authenticator.Response + wantUnauthenticated bool + skipDryRunAuthenticateUser bool // tests about when the end user bind fails don't make sense for DryRunAuthenticateUser() + }{ + { + name: "happy path", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "default as much as possible", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: &ProviderConfig{ + Name: "some-provider-name", + Host: testHost, + CABundle: nil, // this field is only used by the production dialer, which is replaced by a mock for this test + ConnectionProtocol: TLS, + BindUsername: testBindUsername, + BindPassword: testBindPassword, + GroupSearch: GroupSearchConfig{ + Base: testGroupSearchBase, + Filter: testGroupSearchFilter, + GroupNameAttribute: testGroupSearchGroupNameAttribute, + }, + }, + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(func(r *ldap.SearchRequest) { + r.Filter = "(" + sAMAccountNameAttributeName + "=" + testUpstreamUsername + ")" + r.Attributes = []string{sAMAccountNameAttributeName, testUserSearchUIDAttribute} + r.BaseDN = "dc=activedirectory,dc=example,dc=com" + })).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(sAMAccountNameAttributeName, []string{testUserSearchResultUsernameAttributeValue}), + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{testUserSearchResultUIDAttributeValue}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "when the user search filter is already wrapped by parenthesis then it is not wrapped again", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.UserSearch.Filter = "(" + testUserSearchFilter + ")" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "when the group search filter is already wrapped by parenthesis then it is not wrapped again", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.GroupSearch.Filter = "(" + testGroupSearchFilter + ")" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "when the group search base is empty then skip the group search entirely", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.GroupSearch.Base = "" // this configuration means that the user does not want group search to happen + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(func(r *user.DefaultInfo) { + r.Groups = []string{} + }), + }, + { + name: "when the UsernameAttribute is dn and there is a user search filter provided", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.UserSearch.UsernameAttribute = "dn" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(func(r *ldap.SearchRequest) { + r.Attributes = []string{testUserSearchUIDAttribute} + })).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{testUserSearchResultUIDAttributeValue}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(func(r *user.DefaultInfo) { + r.Name = testUserSearchResultDNValue + }), + }, + { + name: "when the UIDAttribute is dn", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.UserSearch.UIDAttribute = "dn" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(func(r *ldap.SearchRequest) { + r.Attributes = []string{testUserSearchUsernameAttribute} + })).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUsernameAttribute, []string{testUserSearchResultUsernameAttributeValue}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(func(r *user.DefaultInfo) { + r.UID = base64.RawURLEncoding.EncodeToString([]byte(testUserSearchResultDNValue)) + }), + }, + { + name: "when the GroupNameAttribute is empty then it defaults to dn", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.GroupSearch.GroupNameAttribute = "" // blank means to use dn + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(func(r *ldap.SearchRequest) { + r.Attributes = []string{} + }), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(func(r *user.DefaultInfo) { + r.Groups = []string{testGroupSearchResultDNValue1, testGroupSearchResultDNValue2} + }), + }, + { + name: "when the GroupNameAttribute is dn", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.GroupSearch.GroupNameAttribute = "dn" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(func(r *ldap.SearchRequest) { + r.Attributes = []string{} + }), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(func(r *user.DefaultInfo) { + r.Groups = []string{testGroupSearchResultDNValue1, testGroupSearchResultDNValue2} + }), + }, + { + name: "when the GroupNameAttribute is cn", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.GroupSearch.GroupNameAttribute = "cn" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(func(r *ldap.SearchRequest) { + r.Attributes = []string{"cn"} + }), expectedGroupSearchPageSize). + Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute("cn", []string{testGroupSearchResultGroupNameAttributeValue1}), + }, + }, + { + DN: testGroupSearchResultDNValue2, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute("cn", []string{testGroupSearchResultGroupNameAttributeValue2}), + }, + }, + }, + Referrals: []string{}, // note that we are not following referrals at this time + Controls: []ldap.Control{}, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "when user search Filter is blank it derives a search filter from the UsernameAttribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.UserSearch.Filter = "" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(func(r *ldap.SearchRequest) { + r.Filter = "(" + testUserSearchUsernameAttribute + "=" + testUpstreamUsername + ")" + })).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "when user search Filter and user attribute is blank it defaults to sAMAccountName={}", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.UserSearch.Filter = "" + p.UserSearch.UsernameAttribute = "" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(func(r *ldap.SearchRequest) { + r.Filter = "(" + sAMAccountNameAttributeName + "=" + testUpstreamUsername + ")" + r.Attributes = []string{sAMAccountNameAttributeName, testUserSearchUIDAttribute} + })).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(sAMAccountNameAttributeName, []string{testUserSearchResultUsernameAttributeValue}), + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{testUserSearchResultUIDAttributeValue}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "when group search Filter is blank it uses a default search filter of member={}", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.GroupSearch.Filter = "" + }), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(func(r *ldap.SearchRequest) { + r.Filter = "(member=" + testUserSearchResultDNValue + ")" + }), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "when the username has special LDAP search filter characters then they must be properly escaped in the search filter, because the username is end-user input", + username: `a&b|c(d)e\f*g`, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(func(r *ldap.SearchRequest) { + r.Filter = fmt.Sprintf("(some-user-filter=%s-and-more-filter=%s)", `a&b|c\28d\29e\5cf\2ag`, `a&b|c\28d\29e\5cf\2ag`) + })).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: expectedAuthResponse(nil), + }, + { + name: "group names are sorted to make the result more stable/predictable", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{"c"}), + }, + }, + { + DN: testGroupSearchResultDNValue2, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{"a"}), + }, + }, + { + DN: testGroupSearchResultDNValue2, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{"b"}), + }, + }, + }, + Referrals: []string{}, // note that we are not following referrals at this time + Controls: []ldap.Control{}, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Times(1) + }, + wantAuthResponse: &authenticator.Response{ + User: &user.DefaultInfo{ + Name: testUserSearchResultUsernameAttributeValue, + UID: "123e4567-e89b-12d3-a456-426614174000", + Groups: []string{"a", "b", "c"}, + }, + }, + }, + { + name: "when dial fails", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + dialError: errors.New("some dial error"), + wantError: fmt.Sprintf(`error dialing host "%s": some dial error`, testHost), + }, + { + name: "when the UsernameAttribute is dn and there is not a user search filter provided", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(func(p *ProviderConfig) { + p.UserSearch.UsernameAttribute = "dn" + p.UserSearch.Filter = "" + }), + wantToSkipDial: true, + wantError: `must specify UserSearch Filter when UserSearch UsernameAttribute is "dn"`, + }, + { + name: "when binding as the bind user returns an error", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Return(errors.New("some bind error")).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf(`error binding as "%s" before user search: some bind error`, testBindUsername), + }, + { + name: "when searching for the user returns an error", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(nil, errors.New("some user search error")).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: `error searching for user: some user search error`, + }, + { + name: "when searching for the user's groups returns an error", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(nil, errors.New("some group search error")).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf(`error searching for group memberships for user with DN "%s": some group search error`, testUserSearchResultDNValue), + }, + { + name: "when searching for the user returns no results", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{}, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantUnauthenticated: true, + }, + { + name: "when searching for the user returns multiple results", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + {DN: testUserSearchResultDNValue}, + {DN: "some-other-dn"}, + }, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf(`searching for user "%s" resulted in 2 search results, but expected 1 result`, testUpstreamUsername), + }, + { + name: "when searching for the user returns a user without a DN", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + {DN: ""}, + }, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf(`searching for user "%s" resulted in search result without DN`, testUpstreamUsername), + }, + { + name: "when searching for the user's groups returns a group without a DN", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{testGroupSearchResultGroupNameAttributeValue1}), + }, + }, + { + DN: "", + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{testGroupSearchResultGroupNameAttributeValue2}), + }, + }, + }, + Referrals: []string{}, // note that we are not following referrals at this time + Controls: []ldap.Control{}, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf( + `searching for group memberships for user with DN "%s" resulted in search result without DN`, + testUserSearchResultDNValue), + }, + { + name: "when searching for the user returns a user without an expected username attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{testUserSearchResultUIDAttributeValue}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf( + `found 0 values for attribute "%s" while searching for user "%s", but expected 1 result`, + testUserSearchUsernameAttribute, testUpstreamUsername), + }, + { + name: "when searching for the group memberships returns a group without an expected group name attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{testGroupSearchResultGroupNameAttributeValue1}), + }, + }, + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute("unrelated attribute", []string{"anything"}), + }, + }, + }, + Referrals: []string{}, // note that we are not following referrals at this time + Controls: []ldap.Control{}, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf( + `error searching for group memberships for user with DN "%s": found 0 values for attribute "%s" while searching for user "%s", but expected 1 result`, + testUserSearchResultDNValue, testGroupSearchGroupNameAttribute, testUserSearchResultDNValue), + }, + { + name: "when searching for the user returns a user with too many values for the expected username attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUsernameAttribute, []string{ + testUserSearchResultUsernameAttributeValue, + "unexpected-additional-value", + }), + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{testUserSearchResultUIDAttributeValue}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf( + `found 2 values for attribute "%s" while searching for user "%s", but expected 1 result`, + testUserSearchUsernameAttribute, testUpstreamUsername), + }, + { + name: "when searching for the group memberships returns a group with too many values for the expected group name attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{testGroupSearchResultGroupNameAttributeValue1}), + }, + }, + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{ + testGroupSearchResultGroupNameAttributeValue1, + "unexpected-additional-value", + }), + }, + }, + }, + Referrals: []string{}, // note that we are not following referrals at this time + Controls: []ldap.Control{}, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf( + `error searching for group memberships for user with DN "%s": found 2 values for attribute "%s" while searching for user "%s", but expected 1 result`, + testUserSearchResultDNValue, testGroupSearchGroupNameAttribute, testUserSearchResultDNValue), + }, + { + name: "when searching for the user returns a user with an empty value for the expected username attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUsernameAttribute, []string{""}), + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{testUserSearchResultUIDAttributeValue}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf( + `found empty value for attribute "%s" while searching for user "%s", but expected value to be non-empty`, + testUserSearchUsernameAttribute, testUpstreamUsername), + }, + { + name: "when searching for the group memberships returns a group with an empty value for for the expected group name attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{testGroupSearchResultGroupNameAttributeValue1}), + }, + }, + { + DN: testGroupSearchResultDNValue1, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testGroupSearchGroupNameAttribute, []string{""}), + }, + }, + }, + Referrals: []string{}, // note that we are not following referrals at this time + Controls: []ldap.Control{}, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf( + `error searching for group memberships for user with DN "%s": found empty value for attribute "%s" while searching for user "%s", but expected value to be non-empty`, + testUserSearchResultDNValue, testGroupSearchGroupNameAttribute, testUserSearchResultDNValue), + }, + { + name: "when searching for the user returns a user without an expected UID attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUsernameAttribute, []string{testUserSearchResultUsernameAttributeValue}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf(`found 0 values for attribute "%s" while searching for user "%s", but expected 1 result`, testUserSearchUIDAttribute, testUpstreamUsername), + }, + { + name: "when searching for the user returns a user with too many values for the expected UID attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUsernameAttribute, []string{testUserSearchResultUsernameAttributeValue}), + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{ + testUserSearchResultUIDAttributeValue, + "unexpected-additional-value", + }), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf(`found 2 values for attribute "%s" while searching for user "%s", but expected 1 result`, testUserSearchUIDAttribute, testUpstreamUsername), + }, + { + name: "when searching for the user returns a user with an empty value for the expected UID attribute", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(&ldap.SearchResult{ + Entries: []*ldap.Entry{ + { + DN: testUserSearchResultDNValue, + Attributes: []*ldap.EntryAttribute{ + ldap.NewEntryAttribute(testUserSearchUsernameAttribute, []string{testUserSearchResultUsernameAttributeValue}), + ldap.NewEntryAttribute(testUserSearchUIDAttribute, []string{""}), + }, + }, + }, + }, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf(`found empty value for attribute "%s" while searching for user "%s", but expected value to be non-empty`, testUserSearchUIDAttribute, testUpstreamUsername), + }, + { + name: "when binding as the found user returns an error", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Return(errors.New("some bind error")).Times(1) + }, + skipDryRunAuthenticateUser: true, + wantError: fmt.Sprintf(`error binding for user "%s" using provided password against DN "%s": some bind error`, testUpstreamUsername, testUserSearchResultDNValue), + }, + { + name: "when binding as the found user returns a specific invalid credentials error", + username: testUpstreamUsername, + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + searchMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Search(expectedUserSearch(nil)).Return(exampleUserSearchResult, nil).Times(1) + conn.EXPECT().SearchWithPaging(expectedGroupSearch(nil), expectedGroupSearchPageSize). + Return(exampleGroupSearchResult, nil).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantUnauthenticated: true, + skipDryRunAuthenticateUser: true, + bindEndUserMocks: func(conn *mockldapconn.MockConn) { + err := &ldap.Error{ + Err: errors.New("some bind error"), + ResultCode: ldap.LDAPResultInvalidCredentials, + } + conn.EXPECT().Bind(testUserSearchResultDNValue, testUpstreamPassword).Return(err).Times(1) + }, + }, + { + name: "when no username is specified", + username: "", + password: testUpstreamPassword, + providerConfig: providerConfig(nil), + wantToSkipDial: true, + wantUnauthenticated: true, + }, + } + + for _, test := range tests { + tt := test + t.Run(tt.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + t.Cleanup(ctrl.Finish) + + conn := mockldapconn.NewMockConn(ctrl) + if tt.searchMocks != nil { + tt.searchMocks(conn) + } + if tt.bindEndUserMocks != nil { + tt.bindEndUserMocks(conn) + } + + dialWasAttempted := false + tt.providerConfig.Dialer = LDAPDialerFunc(func(ctx context.Context, addr endpointaddr.HostPort) (Conn, error) { + dialWasAttempted = true + require.Equal(t, tt.providerConfig.Host, addr.Endpoint()) + if tt.dialError != nil { + return nil, tt.dialError + } + return conn, nil + }) + + provider := New(*tt.providerConfig) + + authResponse, authenticated, err := provider.AuthenticateUser(context.Background(), tt.username, tt.password) + require.Equal(t, !tt.wantToSkipDial, dialWasAttempted) + switch { + case tt.wantError != "": + require.EqualError(t, err, tt.wantError) + require.False(t, authenticated) + require.Nil(t, authResponse) + case tt.wantUnauthenticated: + require.NoError(t, err) + require.False(t, authenticated) + require.Nil(t, authResponse) + default: + require.NoError(t, err) + require.True(t, authenticated) + require.Equal(t, tt.wantAuthResponse, authResponse) + } + + // DryRunAuthenticateUser() should have the same behavior as AuthenticateUser() except that it does not bind + // as the end user to confirm their password. Since it should behave the same, all of the same test cases + // apply, except for those which are specifically testing what happens when the end user bind fails. + if tt.skipDryRunAuthenticateUser { + return // move on to the next test + } + + // Reset some variables to get ready to call DryRunAuthenticateUser(). + dialWasAttempted = false + conn = mockldapconn.NewMockConn(ctrl) + if tt.searchMocks != nil { + tt.searchMocks(conn) + } + // Skip tt.bindEndUserMocks since DryRunAuthenticateUser() never binds as the end user. + + authResponse, authenticated, err = provider.DryRunAuthenticateUser(context.Background(), tt.username) + require.Equal(t, !tt.wantToSkipDial, dialWasAttempted) + switch { + case tt.wantError != "": + require.EqualError(t, err, tt.wantError) + require.False(t, authenticated) + require.Nil(t, authResponse) + case tt.wantUnauthenticated: + require.NoError(t, err) + require.False(t, authenticated) + require.Nil(t, authResponse) + default: + require.NoError(t, err) + require.True(t, authenticated) + require.Equal(t, tt.wantAuthResponse, authResponse) + } + }) + } +} + +func TestTestConnection(t *testing.T) { + providerConfig := func(editFunc func(p *ProviderConfig)) *ProviderConfig { + config := &ProviderConfig{ + Name: "some-provider-name", + Host: testHost, + CABundle: nil, // this field is only used by the production dialer, which is replaced by a mock for this test + ConnectionProtocol: TLS, + BindUsername: testBindUsername, + BindPassword: testBindPassword, + UserSearch: UserSearchConfig{}, // not used by TestConnection + } + if editFunc != nil { + editFunc(config) + } + return config + } + + tests := []struct { + name string + providerConfig *ProviderConfig + setupMocks func(conn *mockldapconn.MockConn) + dialError error + wantError string + wantToSkipDial bool + }{ + { + name: "happy path", + providerConfig: providerConfig(nil), + setupMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Times(1) + conn.EXPECT().Close().Times(1) + }, + }, + { + name: "when dial fails", + providerConfig: providerConfig(nil), + dialError: errors.New("some dial error"), + wantError: fmt.Sprintf(`error dialing host "%s": some dial error`, testHost), + }, + { + name: "when binding as the bind user returns an error", + providerConfig: providerConfig(nil), + setupMocks: func(conn *mockldapconn.MockConn) { + conn.EXPECT().Bind(testBindUsername, testBindPassword).Return(errors.New("some bind error")).Times(1) + conn.EXPECT().Close().Times(1) + }, + wantError: fmt.Sprintf(`error binding as "%s": some bind error`, testBindUsername), + }, + { + name: "when the config is invalid", + providerConfig: providerConfig(func(p *ProviderConfig) { + // This particular combination of options is not allowed. + p.UserSearch.UsernameAttribute = "dn" + p.UserSearch.Filter = "" + }), + wantToSkipDial: true, + wantError: `must specify UserSearch Filter when UserSearch UsernameAttribute is "dn"`, + }, + } + + for _, test := range tests { + tt := test + t.Run(tt.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + t.Cleanup(ctrl.Finish) + + conn := mockldapconn.NewMockConn(ctrl) + if tt.setupMocks != nil { + tt.setupMocks(conn) + } + + dialWasAttempted := false + tt.providerConfig.Dialer = LDAPDialerFunc(func(ctx context.Context, addr endpointaddr.HostPort) (Conn, error) { + dialWasAttempted = true + require.Equal(t, tt.providerConfig.Host, addr.Endpoint()) + if tt.dialError != nil { + return nil, tt.dialError + } + return conn, nil + }) + + provider := New(*tt.providerConfig) + err := provider.TestConnection(context.Background()) + + require.Equal(t, !tt.wantToSkipDial, dialWasAttempted) + + switch { + case tt.wantError != "": + require.EqualError(t, err, tt.wantError) + default: + require.NoError(t, err) + } + }) + } +} + +func TestGetConfig(t *testing.T) { + c := ProviderConfig{ + Name: "original-provider-name", + Host: testHost, + CABundle: []byte("some-ca-bundle"), + BindUsername: testBindUsername, + BindPassword: testBindPassword, + UserSearch: UserSearchConfig{ + Base: testUserSearchBase, + Filter: testUserSearchFilter, + UsernameAttribute: testUserSearchUsernameAttribute, + UIDAttribute: testUserSearchUIDAttribute, + }, + } + p := New(c) + require.Equal(t, c, p.c) + require.Equal(t, c, p.GetConfig()) + + // The original config can be changed without impacting the provider, since the provider made a copy of the config. + c.Name = "changed-name" + require.Equal(t, "original-provider-name", p.c.Name) + + // The return value of GetConfig can be modified without impacting the provider, since it is a copy of the config. + returnedConfig := p.GetConfig() + returnedConfig.Name = "changed-name" + require.Equal(t, "original-provider-name", p.c.Name) +} + +func TestGetURL(t *testing.T) { + require.Equal(t, + "ldaps://ldap.example.com:1234?base=ou%3Dusers%2Cdc%3Dpinniped%2Cdc%3Ddev", + New(ProviderConfig{ + Host: "ldap.example.com:1234", + UserSearch: UserSearchConfig{Base: "ou=users,dc=pinniped,dc=dev"}, + }).GetURL().String()) + + require.Equal(t, + "ldaps://ldap.example.com?base=ou%3Dusers%2Cdc%3Dpinniped%2Cdc%3Ddev", + New(ProviderConfig{ + Host: "ldap.example.com", + UserSearch: UserSearchConfig{Base: "ou=users,dc=pinniped,dc=dev"}, + }).GetURL().String()) +} + +// Testing of host parsing, TLS negotiation, and CA bundle, etc. for the production code's dialer. +func TestRealTLSDialing(t *testing.T) { + testServerCABundle, testServerURL := testutil.TLSTestServer(t, func(w http.ResponseWriter, r *http.Request) {}) + parsedURL, err := url.Parse(testServerURL) + require.NoError(t, err) + testServerHostAndPort := parsedURL.Host + + caForTestServerWithBadCertName, err := certauthority.New("Test CA", time.Hour) + require.NoError(t, err) + wrongIP := net.ParseIP("10.2.3.4") + cert, err := caForTestServerWithBadCertName.IssueServerCert([]string{"wrong-dns-name"}, []net.IP{wrongIP}, time.Hour) + require.NoError(t, err) + testServerWithBadCertNameAddr := testutil.TLSTestServerWithCert(t, func(w http.ResponseWriter, r *http.Request) {}, cert) + + unusedPortGrabbingListener, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + recentlyClaimedHostAndPort := unusedPortGrabbingListener.Addr().String() + require.NoError(t, unusedPortGrabbingListener.Close()) + + alreadyCancelledContext, cancelFunc := context.WithCancel(context.Background()) + cancelFunc() // cancel it immediately + + tests := []struct { + name string + host string + connProto LDAPConnectionProtocol + caBundle []byte + context context.Context + wantError string + }{ + { + name: "happy path", + host: testServerHostAndPort, + caBundle: []byte(testServerCABundle), + connProto: TLS, + context: context.Background(), + }, + { + name: "server cert name does not match the address to which the client connected", + host: testServerWithBadCertNameAddr, + caBundle: caForTestServerWithBadCertName.Bundle(), + connProto: TLS, + context: context.Background(), + wantError: `LDAP Result Code 200 "Network Error": x509: certificate is valid for 10.2.3.4, not 127.0.0.1`, + }, + { + name: "invalid CA bundle with TLS", + host: testServerHostAndPort, + caBundle: []byte("not a ca bundle"), + connProto: TLS, + context: context.Background(), + wantError: `LDAP Result Code 200 "Network Error": could not parse CA bundle`, + }, + { + name: "invalid CA bundle with StartTLS", + host: testServerHostAndPort, + caBundle: []byte("not a ca bundle"), + connProto: StartTLS, + context: context.Background(), + wantError: `LDAP Result Code 200 "Network Error": could not parse CA bundle`, + }, + { + name: "invalid host with TLS", + host: "this:is:not:a:valid:hostname", + caBundle: []byte(testServerCABundle), + connProto: TLS, + context: context.Background(), + wantError: `LDAP Result Code 200 "Network Error": host "this:is:not:a:valid:hostname" is not a valid hostname or IP address`, + }, + { + name: "invalid host with StartTLS", + host: "this:is:not:a:valid:hostname", + caBundle: []byte(testServerCABundle), + connProto: StartTLS, + context: context.Background(), + wantError: `LDAP Result Code 200 "Network Error": host "this:is:not:a:valid:hostname" is not a valid hostname or IP address`, + }, + { + name: "missing CA bundle when it is required because the host is not using a trusted CA", + host: testServerHostAndPort, + caBundle: nil, + connProto: TLS, + context: context.Background(), + wantError: `LDAP Result Code 200 "Network Error": x509: certificate signed by unknown authority`, + }, + { + name: "cannot connect to host", + // This is assuming that this port was not reclaimed by another app since the test setup ran. Seems safe enough. + host: recentlyClaimedHostAndPort, + caBundle: []byte(testServerCABundle), + connProto: TLS, + context: context.Background(), + wantError: fmt.Sprintf(`LDAP Result Code 200 "Network Error": dial tcp %s: connect: connection refused`, recentlyClaimedHostAndPort), + }, + { + name: "pays attention to the passed context", + host: testServerHostAndPort, + caBundle: []byte(testServerCABundle), + connProto: TLS, + context: alreadyCancelledContext, + wantError: fmt.Sprintf(`LDAP Result Code 200 "Network Error": dial tcp %s: operation was canceled`, testServerHostAndPort), + }, + { + name: "unsupported connection protocol", + host: testServerHostAndPort, + caBundle: []byte(testServerCABundle), + connProto: "bad usage of this type", + context: alreadyCancelledContext, + wantError: `LDAP Result Code 200 "Network Error": did not specify valid ConnectionProtocol`, + }, + } + for _, test := range tests { + tt := test + t.Run(tt.name, func(t *testing.T) { + provider := New(ProviderConfig{ + Host: tt.host, + CABundle: tt.caBundle, + ConnectionProtocol: tt.connProto, + Dialer: nil, // this test is for the default (production) TLS dialer + }) + conn, err := provider.dial(tt.context) + if conn != nil { + defer conn.Close() + } + if tt.wantError != "" { + require.Nil(t, conn) + require.EqualError(t, err, tt.wantError) + } else { + require.NoError(t, err) + require.NotNil(t, conn) + + // Should be an instance of the real production LDAP client type. + // Can't test its methods here because we are not dialed to a real LDAP server. + require.IsType(t, &ldap.Conn{}, conn) + + // Indirectly checking that the Dialer method constructed the ldap.Conn with isTLS set to true, + // since this is always the correct behavior unless/until we want to support StartTLS. + err := conn.(*ldap.Conn).StartTLS(&tls.Config{}) + require.EqualError(t, err, `LDAP Result Code 200 "Network Error": ldap: already encrypted`) + } + }) + } +}