diff --git a/PROJECT b/PROJECT index c4c87a0bc7ae5dd78feaac2be7433ac6f8a2f574..3b04f5a30da63be83264735302e49a44516e03d5 100644 --- a/PROJECT +++ b/PROJECT @@ -35,4 +35,12 @@ resources: kind: Realm path: libre.sh/controller/apis/apps/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + domain: libre.sh + group: apps + kind: LibreConfig + path: libre.sh/controller/apis/apps/v1alpha1 + version: v1alpha1 version: "3" diff --git a/apis/apps/v1alpha1/libreconfig_types.go b/apis/apps/v1alpha1/libreconfig_types.go new file mode 100644 index 0000000000000000000000000000000000000000..b41e278508d906361201f8db9665b4605930d176 --- /dev/null +++ b/apis/apps/v1alpha1/libreconfig_types.go @@ -0,0 +1,60 @@ +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// LibreConfigSpec defines the desired state of LibreConfig +type LibreConfigSpec struct { + // Keycloak provider + // +optinal + Keycloak *Provider `json:"keycloak,omitempty"` + // Data ObjectStore provider + // +optinal + DataObjectStore *Provider `json:"dataObjectStore,omitempty"` + // Backup ObjectStore provider + // +optional + BackupObjectStore *Provider `json:"backupObjectStore,omitempty"` + // Email provider + // +optinal + Email *Provider `json:"email,omitempty"` +} + +type Provider struct { + // Keycloak host url + // +required + Host string `json:"hostname,omitempty"` + // Secret reference with information for to connect to the api. Keys must be - username, password + // +required + Credentials *corev1.LocalObjectReference `json:"credentials,omitempty"` +} + +// LibreConfigStatus defines the observed state of LibreConfig +type LibreConfigStatus struct { +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// LibreConfig is the Schema for the libreconfigs API +type LibreConfig struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec LibreConfigSpec `json:"spec,omitempty"` + Status LibreConfigStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// LibreConfigList contains a list of LibreConfig +type LibreConfigList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []LibreConfig `json:"items"` +} + +func init() { + SchemeBuilder.Register(&LibreConfig{}, &LibreConfigList{}) +} diff --git a/apis/apps/v1alpha1/nextcloud_types.go b/apis/apps/v1alpha1/nextcloud_types.go index edcb9a660f8a77d9eed8fabf13090e6d47f9faab..b2923e7aea664da79d868bab97ac36b1f680547d 100644 --- a/apis/apps/v1alpha1/nextcloud_types.go +++ b/apis/apps/v1alpha1/nextcloud_types.go @@ -4,22 +4,13 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - // NextcloudSpec defines the desired state of Nextcloud type NextcloudSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file - - // Foo is an example field of Nextcloud. Edit nextcloud_types.go to remove/update Foo string `json:"foo,omitempty"` } // NextcloudStatus defines the observed state of Nextcloud type NextcloudStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file } //+kubebuilder:object:root=true diff --git a/apis/apps/v1alpha1/realm_types.go b/apis/apps/v1alpha1/realm_types.go index 6f00e206c06dc4e268bd93e5882e6c1cdb6acc76..c7b61a3a5e1d6a9a454881b21cb55f1413ddd6c9 100644 --- a/apis/apps/v1alpha1/realm_types.go +++ b/apis/apps/v1alpha1/realm_types.go @@ -4,18 +4,165 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - // RealmSpec defines the desired state of Realm type RealmSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file + // Realm Name, default to metada.name + Name string `json:"name,omitempty"` + // Is Realm enabled + // +optional + Enabled bool `json:"enabled,omitempty"` + // Realm display name. + // +optional + DisplayName string `json:"displayName"` + // Realm HTML display name. + // +optional + DisplayNameHTML string `json:"displayNameHtml,omitempty"` + // Are metrics enabled + // +optional + Metrics bool `json:"metrics,omitempty"` + + // Login Theme + // +optional + LoginTheme string `json:"loginTheme,omitempty"` + // Account Theme + // +optional + AccountTheme string `json:"accountTheme,omitempty"` + // Admin Console Theme + // +optional + AdminTheme string `json:"adminTheme,omitempty"` + // Email Theme + // +optional + EmailTheme string `json:"emailTheme,omitempty"` + // Internationalization Enabled + // +optional + InternationalizationEnabled *bool `json:"internationalizationEnabled,omitempty"` + // Supported Locales + // +optional + SupportedLocales []string `json:"supportedLocales,omitempty"` + // Default Locale + // +optional + DefaultLocale string `json:"defaultLocale,omitempty"` + + // User registration + // +optional + RegistrationAllowed *bool `json:"registrationAllowed,omitempty"` + // Email as username + // +optional + RegistrationEmailAsUsername *bool `json:"registrationEmailAsUsername,omitempty"` + // Edit username + // +optional + EditUsernameAllowed *bool `json:"editUsernameAllowed,omitempty"` + // Forgot password + // +optional + ResetPasswordAllowed *bool `json:"resetPasswordAllowed,omitempty"` + // Remember me + // +optional + RememberMe *bool `json:"rememberMe,omitempty"` + // Verify email + // +optional + VerifyEmail *bool `json:"verifyEmail,omitempty"` + // Login with email + // +optional + LoginWithEmailAllowed *bool `json:"loginWithEmailAllowed,omitempty"` + // Duplicate emails + // +optional + DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"` - // Foo is an example field of Realm. Edit realm_types.go to remove/update - Foo string `json:"foo,omitempty"` + // Default to 1 Day + // +optional + SSOSessionIdleTimeoutRememberMe string `json:"ssoSessionIdleTimeoutRememberMe,omitempty"` + // Default to 7 Days + // +optional + SSOSessionMaxLifespanRememberMe string `json:"ssoSessionMaxLifespanRememberMe,omitempty"` + + // Authorized domains for Content Security Policy + // +optional + ContentSecurityPolicy []string `json:"contentSecurityPolicy,omitempty"` } +/* +r.RegistrationEmailAsUsername = gocloak.BoolP(false) + + r.InternationalizationEnabled = gocloak.BoolP(true) + + r.SupportedLocales = &[]string{"fr", "en"} + + r.RegistrationAllowed = gocloak.BoolP(false) + + r.LoginWithEmailAllowed = gocloak.BoolP(true) + + r.VerifyEmail = gocloak.BoolP(true) + + r.RememberMe = gocloak.BoolP(true) + + r.ResetPasswordAllowed = gocloak.BoolP(true) + + r.EditUsernameAllowed = gocloak.BoolP(false) + + r.DuplicateEmailsAllowed = gocloak.BoolP(false) + + r.DisplayName = gocloak.StringP(strings.Replace(conf.Domain, ".", "-", -1)) + + r.DisplayNameHTML = gocloak.StringP(strings.Replace(conf.Domain, ".", "-", -1)) + + r.AdminTheme = gocloak.StringP("liiibre") + + r.EmailTheme = gocloak.StringP("liiibrelite") + + r.LoginTheme = gocloak.StringP("liiibrelite") + + r.AccountTheme = gocloak.StringP("liiibre") + + r.RememberMe = gocloak.BoolP(true) + + r.BruteForceProtected = gocloak.BoolP(true) + + // 1 Day + r.SsoSessionIdleTimeoutRememberMe = gocloak.IntP(86400) + // 7 Days + r.SsoSessionMaxLifespanRememberMe = gocloak.IntP(604800) + + browserSecurityHeaders := map[string]string{ + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + // TODO + "contentSecurityPolicy": fmt.Sprintf("frame-src 'self' %s; frame-ancestors 'self' %s; object-src 'none';", conf.Nextcloud.GetURL(), conf.Nextcloud.GetURL()), + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains", + } + + r.BrowserSecurityHeaders = &browserSecurityHeaders + + secret := &corev1.Secret{} + err := k8sCLI.Get(context.TODO(), client.ObjectKey{ + Namespace: conf.Keycloak.Realm, + Name: fmt.Sprintf("%s-smtp", conf.Keycloak.Realm)}, + secret) + if err != nil { + // TODO manage error, if secret does not exist skip ? + return err + } + + smtp := map[string]string{ + "auth": strconv.FormatBool(true), + "user": string(secret.Data["username"]), + "from": string(secret.Data["username"]), + "password": string(secret.Data["password"]), + "host": string(secret.Data["host"]), + "Host": string(secret.Data["host"]), + "port": string(secret.Data["port"]), + "Port": string(secret.Data["port"]), + "starttls": strconv.FormatBool(true), + } + + r.SMTPServer = &smtp + + r.PasswordPolicy = gocloak.StringP("length(12) and notUsername(undefined) and passwordHistory(3)") + + return nil +*/ + // RealmStatus defines the observed state of Realm type RealmStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster diff --git a/apis/apps/v1alpha1/zz_generated.deepcopy.go b/apis/apps/v1alpha1/zz_generated.deepcopy.go index df2acf97b38a85980c06fe453951b23e740f727a..64da3dcf223862b7cf6c68aee95aeb8871efe2ea 100644 --- a/apis/apps/v1alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v1alpha1/zz_generated.deepcopy.go @@ -6,9 +6,99 @@ package v1alpha1 import ( + "k8s.io/api/core/v1" 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 *LibreConfig) DeepCopyInto(out *LibreConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LibreConfig. +func (in *LibreConfig) DeepCopy() *LibreConfig { + if in == nil { + return nil + } + out := new(LibreConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LibreConfig) 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 *LibreConfigList) DeepCopyInto(out *LibreConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LibreConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LibreConfigList. +func (in *LibreConfigList) DeepCopy() *LibreConfigList { + if in == nil { + return nil + } + out := new(LibreConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LibreConfigList) 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 *LibreConfigSpec) DeepCopyInto(out *LibreConfigSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LibreConfigSpec. +func (in *LibreConfigSpec) DeepCopy() *LibreConfigSpec { + if in == nil { + return nil + } + out := new(LibreConfigSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LibreConfigStatus) DeepCopyInto(out *LibreConfigStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LibreConfigStatus. +func (in *LibreConfigStatus) DeepCopy() *LibreConfigStatus { + if in == nil { + return nil + } + out := new(LibreConfigStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Nextcloud) DeepCopyInto(out *Nextcloud) { *out = *in @@ -103,7 +193,7 @@ func (in *Realm) DeepCopyInto(out *Realm) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) out.Status = in.Status } @@ -160,6 +250,61 @@ func (in *RealmList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RealmSpec) DeepCopyInto(out *RealmSpec) { *out = *in + if in.APIClient != nil { + in, out := &in.APIClient, &out.APIClient + *out = new(v1.SecretReference) + **out = **in + } + if in.InternationalizationEnabled != nil { + in, out := &in.InternationalizationEnabled, &out.InternationalizationEnabled + *out = new(bool) + **out = **in + } + if in.SupportedLocales != nil { + in, out := &in.SupportedLocales, &out.SupportedLocales + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.RegistrationAllowed != nil { + in, out := &in.RegistrationAllowed, &out.RegistrationAllowed + *out = new(bool) + **out = **in + } + if in.RegistrationEmailAsUsername != nil { + in, out := &in.RegistrationEmailAsUsername, &out.RegistrationEmailAsUsername + *out = new(bool) + **out = **in + } + if in.EditUsernameAllowed != nil { + in, out := &in.EditUsernameAllowed, &out.EditUsernameAllowed + *out = new(bool) + **out = **in + } + if in.ResetPasswordAllowed != nil { + in, out := &in.ResetPasswordAllowed, &out.ResetPasswordAllowed + *out = new(bool) + **out = **in + } + if in.RememberMe != nil { + in, out := &in.RememberMe, &out.RememberMe + *out = new(bool) + **out = **in + } + if in.VerifyEmail != nil { + in, out := &in.VerifyEmail, &out.VerifyEmail + *out = new(bool) + **out = **in + } + if in.LoginWithEmailAllowed != nil { + in, out := &in.LoginWithEmailAllowed, &out.LoginWithEmailAllowed + *out = new(bool) + **out = **in + } + if in.DuplicateEmailsAllowed != nil { + in, out := &in.DuplicateEmailsAllowed, &out.DuplicateEmailsAllowed + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RealmSpec. diff --git a/config/crd/base/apps.libre.sh_nextclouds.yaml b/config/crd/base/apps.libre.sh_nextclouds.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a169bf4173c46763b7e81a790ebc3e60d1ee5039 --- /dev/null +++ b/config/crd/base/apps.libre.sh_nextclouds.yaml @@ -0,0 +1,56 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + creationTimestamp: null + name: nextclouds.apps.libre.sh +spec: + group: apps.libre.sh + names: + kind: Nextcloud + listKind: NextcloudList + plural: nextclouds + singular: nextcloud + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Nextcloud is the Schema for the nextclouds API + 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: NextcloudSpec defines the desired state of Nextcloud + properties: + foo: + description: Foo is an example field of Nextcloud. Edit nextcloud_types.go + to remove/update + type: string + type: object + status: + description: NextcloudStatus defines the observed state of Nextcloud + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/base/apps.libre.sh_realms.yaml b/config/crd/base/apps.libre.sh_realms.yaml new file mode 100644 index 0000000000000000000000000000000000000000..71dc8e51c8be02b30c0fafe86e31353f4d984d05 --- /dev/null +++ b/config/crd/base/apps.libre.sh_realms.yaml @@ -0,0 +1,117 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + creationTimestamp: null + name: realms.apps.libre.sh +spec: + group: apps.libre.sh + names: + kind: Realm + listKind: RealmList + plural: realms + singular: realm + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Realm is the Schema for the realms API + 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: RealmSpec defines the desired state of Realm + properties: + accountTheme: + description: Account Theme + type: string + adminTheme: + description: Admin Console Theme + type: string + defaultLocale: + description: Default Locale + type: string + displayName: + description: Realm display name. + type: string + displayNameHtml: + description: Realm HTML display name. + type: string + duplicateEmailsAllowed: + description: Duplicate emails + type: boolean + editUsernameAllowed: + description: Edit username + type: boolean + emailTheme: + description: Email Theme + type: string + enabled: + description: Is Realm enabled + type: boolean + internationalizationEnabled: + description: Internationalization Enabled + type: boolean + loginTheme: + description: Login Theme + type: string + loginWithEmailAllowed: + description: Login with email + type: boolean + metrics: + description: Are metrics enabled + type: boolean + name: + description: Realm Name, default to metada.name + type: string + registrationAllowed: + description: User registration + type: boolean + registrationEmailAsUsername: + description: Email as username + type: boolean + rememberMe: + description: Remember me + type: boolean + resetPasswordAllowed: + description: Forgot password + type: boolean + scim: + description: Is SCIM Enabled + type: boolean + supportedLocales: + description: Supported Locales + items: + type: string + type: array + verifyEmail: + description: Verify email + type: boolean + type: object + status: + description: RealmStatus defines the observed state of Realm + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/base/apps.libre.sh_rocketchats.yaml b/config/crd/base/apps.libre.sh_rocketchats.yaml new file mode 100644 index 0000000000000000000000000000000000000000..852fcbd1de584ffa0c1a09adcbe94585f565e681 --- /dev/null +++ b/config/crd/base/apps.libre.sh_rocketchats.yaml @@ -0,0 +1,56 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + creationTimestamp: null + name: rocketchats.apps.libre.sh +spec: + group: apps.libre.sh + names: + kind: RocketChat + listKind: RocketChatList + plural: rocketchats + singular: rocketchat + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: RocketChat is the Schema for the rocketchats API + 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: RocketChatSpec defines the desired state of RocketChat + properties: + domain: + type: string + enableOAuth: + type: boolean + type: object + status: + description: RocketChatStatus defines the observed state of RocketChat + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/bases/apps.libre.sh_realms.yaml b/config/crd/bases/apps.libre.sh_realms.yaml index 1c7c3cb76bdccf04526ac9cb432166f5beb4855c..71dc8e51c8be02b30c0fafe86e31353f4d984d05 100644 --- a/config/crd/bases/apps.libre.sh_realms.yaml +++ b/config/crd/bases/apps.libre.sh_realms.yaml @@ -35,10 +35,71 @@ spec: spec: description: RealmSpec defines the desired state of Realm properties: - foo: - description: Foo is an example field of Realm. Edit realm_types.go - to remove/update + accountTheme: + description: Account Theme type: string + adminTheme: + description: Admin Console Theme + type: string + defaultLocale: + description: Default Locale + type: string + displayName: + description: Realm display name. + type: string + displayNameHtml: + description: Realm HTML display name. + type: string + duplicateEmailsAllowed: + description: Duplicate emails + type: boolean + editUsernameAllowed: + description: Edit username + type: boolean + emailTheme: + description: Email Theme + type: string + enabled: + description: Is Realm enabled + type: boolean + internationalizationEnabled: + description: Internationalization Enabled + type: boolean + loginTheme: + description: Login Theme + type: string + loginWithEmailAllowed: + description: Login with email + type: boolean + metrics: + description: Are metrics enabled + type: boolean + name: + description: Realm Name, default to metada.name + type: string + registrationAllowed: + description: User registration + type: boolean + registrationEmailAsUsername: + description: Email as username + type: boolean + rememberMe: + description: Remember me + type: boolean + resetPasswordAllowed: + description: Forgot password + type: boolean + scim: + description: Is SCIM Enabled + type: boolean + supportedLocales: + description: Supported Locales + items: + type: string + type: array + verifyEmail: + description: Verify email + type: boolean type: object status: description: RealmStatus defines the observed state of Realm diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 45cad9ae278ab19f33fc460f8544904fe2cf0c4f..54ee10af809daebf5d72b8a8a1a1332ba2c65980 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -5,6 +5,7 @@ resources: - bases/apps.libre.sh_nextclouds.yaml - bases/apps.libre.sh_rocketchats.yaml - bases/apps.libre.sh_realms.yaml +- bases/apps.libre.sh_libreconfigs.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -13,6 +14,7 @@ patchesStrategicMerge: #- patches/webhook_in_nextclouds.yaml #- patches/webhook_in_rocketchats.yaml #- patches/webhook_in_realms.yaml +#- patches/webhook_in_libreconfigs.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. @@ -20,6 +22,7 @@ patchesStrategicMerge: #- patches/cainjection_in_nextclouds.yaml #- patches/cainjection_in_rocketchats.yaml #- patches/cainjection_in_realms.yaml +#- patches/cainjection_in_libreconfigs.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_apps_libreconfigs.yaml b/config/crd/patches/cainjection_in_apps_libreconfigs.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ef9774c9a66be33177bf5a4acb1827b641500d16 --- /dev/null +++ b/config/crd/patches/cainjection_in_apps_libreconfigs.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: libreconfigs.apps.libre.sh diff --git a/config/crd/patches/webhook_in_apps_libreconfigs.yaml b/config/crd/patches/webhook_in_apps_libreconfigs.yaml new file mode 100644 index 0000000000000000000000000000000000000000..745fb24d5185937ba5f88f04e07011916be124f8 --- /dev/null +++ b/config/crd/patches/webhook_in_apps_libreconfigs.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: libreconfigs.apps.libre.sh +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/rbac/apps_libreconfig_editor_role.yaml b/config/rbac/apps_libreconfig_editor_role.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1da4de23c2a9fae5ba83f8c1bb85821571607330 --- /dev/null +++ b/config/rbac/apps_libreconfig_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit libreconfigs. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: libreconfig-editor-role +rules: +- apiGroups: + - apps.libre.sh + resources: + - libreconfigs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps.libre.sh + resources: + - libreconfigs/status + verbs: + - get diff --git a/config/rbac/apps_libreconfig_viewer_role.yaml b/config/rbac/apps_libreconfig_viewer_role.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a379225e820bdd5b9762185544c1c3e2dd11df55 --- /dev/null +++ b/config/rbac/apps_libreconfig_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view libreconfigs. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: libreconfig-viewer-role +rules: +- apiGroups: + - apps.libre.sh + resources: + - libreconfigs + verbs: + - get + - list + - watch +- apiGroups: + - apps.libre.sh + resources: + - libreconfigs/status + verbs: + - get diff --git a/config/samples/apps_v1alpha1_libreconfig.yaml b/config/samples/apps_v1alpha1_libreconfig.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8eadd00af6b6c65f44002a6c5d252e132cd4ff05 --- /dev/null +++ b/config/samples/apps_v1alpha1_libreconfig.yaml @@ -0,0 +1,6 @@ +apiVersion: apps.libre.sh/v1alpha1 +kind: LibreConfig +metadata: + name: libreconfig-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 0f1165f50609a2322dc40ea1c8b3c250ddfdbe5e..f5bbaa7191b6368232d7021c2fef9df33be5895d 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -3,4 +3,5 @@ resources: - apps_v1alpha1_nextcloud.yaml - apps_v1alpha1_rocketchat.yaml - apps_v1alpha1_realm.yaml +- apps_v1alpha1_libreconfig.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/controllers/apps/realm_controller.go b/controllers/apps/realm_controller.go index 0823837d06a3d55763946b4188547b7f8196a538..313ddaf86041b19dadaec6a01b294e27524a86dc 100644 --- a/controllers/apps/realm_controller.go +++ b/controllers/apps/realm_controller.go @@ -2,12 +2,15 @@ package apps import ( "context" + "fmt" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/Nerzal/gocloak/v11" + appsv1alpha1 "libre.sh/controller/apis/apps/v1alpha1" ) @@ -33,8 +36,24 @@ type RealmReconciler struct { func (r *RealmReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { _ = log.FromContext(ctx) - // TODO(user): your logic here + var realm appsv1alpha1.Realm + err := r.Client.Get(ctx, req.NamespacedName, &realm) + if err != nil { + return ctrl.Result{}, client.IgnoreNotFound(err) + } + + keycloakClient := gocloak.NewClient("https://mycool.keycloak.instance") + token, err := keycloakClient.LoginAdmin(ctx, "user", "password", "realmName") + if err != nil { + return ctrl.Result{}, err + } + + realmRepresentation, err := keycloakClient.GetRealm(ctx, token.AccessToken, realm.Name) + if err != nil { + return ctrl.Result{}, err + } + fmt.Println(realmRepresentation) return ctrl.Result{}, nil } diff --git a/go.mod b/go.mod index 1ac8762d0e7f646a5d78ff034104cb4935974031..5cb85690cd943e0fddfa57c3702e58ccb7a7569e 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,10 @@ module libre.sh/controller go 1.17 require ( + github.com/Nerzal/gocloak/v11 v11.2.0 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.17.0 + k8s.io/api v0.23.0 k8s.io/apimachinery v0.23.0 k8s.io/client-go v0.23.0 sigs.k8s.io/controller-runtime v0.11.0 @@ -26,7 +28,9 @@ require ( github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/go-logr/logr v1.2.0 // indirect github.com/go-logr/zapr v1.2.0 // indirect + github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.4.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.5 // indirect @@ -39,20 +43,22 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/nxadm/tail v1.4.8 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.28.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect + github.com/segmentio/ksuid v1.0.4 // indirect github.com/spf13/pflag v1.0.5 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.19.1 // indirect - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect + golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect + golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect - golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 // indirect - golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect @@ -62,7 +68,6 @@ require ( gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - k8s.io/api v0.23.0 // indirect k8s.io/apiextensions-apiserver v0.23.0 // indirect k8s.io/component-base v0.23.0 // indirect k8s.io/klog/v2 v2.30.0 // indirect diff --git a/go.sum b/go.sum index c7f720bb5c23e2c9b1e9aad97d53163f2f582b69..f0f843b7e7d7eedc25320bb155c3a21902af7460 100644 --- a/go.sum +++ b/go.sum @@ -58,6 +58,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/Nerzal/gocloak/v11 v11.2.0 h1:i67+hsEhSaolpJi1YKgwqH4dtSd8IdfHiEluxSEMm/U= +github.com/Nerzal/gocloak/v11 v11.2.0/go.mod h1:vz59u7bBDKWoCdeTpY8i4LELtdwrLrIynAgPvO5ogQA= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= @@ -165,6 +167,8 @@ github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL9 github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= +github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -173,6 +177,8 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ= +github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -367,6 +373,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -411,6 +419,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= +github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -444,8 +454,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -508,8 +519,9 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -591,8 +603,11 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -683,11 +698,13 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 h1:M69LAlWZCshgp0QSzyDcSsSIejIEeuaCVpmwcKwyLMk= golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=