feat: Advanced authorization (#1789)

* feat: Advanced authorization

Signed-off-by: Anatolii Bazko <abazko@redhat.com>
pull/1795/head
Anatolii Bazko 2023-12-04 17:09:27 +01:00 committed by GitHub
parent 038eaa55f4
commit d99f8923f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 492 additions and 56 deletions

View File

@ -21,16 +21,26 @@ che-operator Development Guide: https://github.com/eclipse-che/che-operator/#dev
- steps to reproduce - steps to reproduce
--> -->
1. Prepare a patch file if needed:
```bash ```bash
cat > /tmp/patch.yaml <<EOF cat > /tmp/cr-patch.yaml <<EOF
<PATCH_CONTENT> apiVersion: org.eclipse.che/v2
kind: CheCluster
spec: {}
EOF EOF
```
chectl server:deploy \ 2. Deploy the operator:
--installer operator \
--platform <PLATFORM_TO_DEPLOY> \ #### OpenShift
--che-operator-image <CUSTOM_OPERATOR_IMAGE> \ ```bash
--che-operator-cr-patch-yaml /tmp/patch.yaml ./build/scripts/olm/test-catalog-from-sources.sh --cr-patch-yaml /tmp/cr-patch.yaml
```
#### on Minikube
```bash
./build/scripts/minikube-tests/test-operator-from-sources.sh --cr-patch-yaml /tmp/cr-patch.yaml
``` ```
### PR Checklist ### PR Checklist

View File

@ -524,6 +524,28 @@ type Auth struct {
// +optional // +optional
// +kubebuilder:default:={configLabels: {app: che, component: che-gateway-config}} // +kubebuilder:default:={configLabels: {app: che, component: che-gateway-config}}
Gateway Gateway `json:"gateway,omitempty"` Gateway Gateway `json:"gateway,omitempty"`
// Advance authorization settings. Determines which users and groups are allowed to access Che.
// User is allowed to access Che if he/she is either in the `allowUsers` list or is member of group from `allowGroups` list
// and not in neither the `denyUsers` list nor is member of group from `denyGroups` list.
// If `allowUsers` and `allowGroups` are empty, then all users are allowed to access Che.
// if `denyUsers` and `denyGroups` are empty, then no users are denied to access Che.
// +optional
AdvancedAuthorization *AdvancedAuthorization `json:"advancedAuthorization,omitempty"`
}
type AdvancedAuthorization struct {
// List of users allowed to access Che.
// +optional
AllowUsers []string `json:"allowUsers,omitempty"`
// List of groups allowed to access Che (currently supported in OpenShift only).
// +optional
AllowGroups []string `json:"allowGroups,omitempty"`
// List of users denied to access Che.
// +optional
DenyUsers []string `json:"denyUsers,omitempty"`
// List of groups denied to access Che (currently supported in OpenShift only).
// +optional
DenyGroups []string `json:"denyGroups,omitempty"`
} }
// Gateway settings. // Gateway settings.

View File

@ -24,6 +24,41 @@ import (
"k8s.io/apimachinery/pkg/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 *AdvancedAuthorization) DeepCopyInto(out *AdvancedAuthorization) {
*out = *in
if in.AllowUsers != nil {
in, out := &in.AllowUsers, &out.AllowUsers
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.AllowGroups != nil {
in, out := &in.AllowGroups, &out.AllowGroups
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.DenyUsers != nil {
in, out := &in.DenyUsers, &out.DenyUsers
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.DenyGroups != nil {
in, out := &in.DenyGroups, &out.DenyGroups
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdvancedAuthorization.
func (in *AdvancedAuthorization) DeepCopy() *AdvancedAuthorization {
if in == nil {
return nil
}
out := new(AdvancedAuthorization)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Auth) DeepCopyInto(out *Auth) { func (in *Auth) DeepCopyInto(out *Auth) {
*out = *in *out = *in
@ -38,6 +73,11 @@ func (in *Auth) DeepCopyInto(out *Auth) {
**out = **in **out = **in
} }
in.Gateway.DeepCopyInto(&out.Gateway) in.Gateway.DeepCopyInto(&out.Gateway)
if in.AdvancedAuthorization != nil {
in, out := &in.AdvancedAuthorization, &out.AdvancedAuthorization
*out = new(AdvancedAuthorization)
(*in).DeepCopyInto(*out)
}
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Auth. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Auth.

View File

@ -0,0 +1,64 @@
#!/usr/bin/env bash
#
# Copyright (c) 2019-2023 Red Hat, Inc.
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
# Red Hat, Inc. - initial API and implementation
#
set -e
OPERATOR_REPO=$(dirname "$(dirname "$(dirname "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")")")
source "${OPERATOR_REPO}/build/scripts/minikube-tests/common.sh"
init() {
unset CR_PATCH_YAML
while [[ "$#" -gt 0 ]]; do
case $1 in
'--help'|'-h') usage; exit;;
'--cr-patch-yaml') CR_PATCH_YAML=$2; shift 1;;
esac
shift 1
done
}
usage () {
echo "Deploy Eclipse Che from sources"
echo
echo "Usage:"
echo -e "\t$0 [--cr-patch-yaml <path_to_cr_patch>]"
echo
echo "OPTIONS:"
echo -e "\t--cr-patch-yaml CheCluster CR patch yaml file"
echo
echo "Example:"
echo -e "\t$0"
}
runTest() {
buildAndCopyCheOperatorImageToMinikube
yq -riSY '.spec.template.spec.containers[0].image = "'${OPERATOR_IMAGE}'"' "${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH}/che-operator/kubernetes/operator.yaml"
yq -riSY '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' "${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH}/che-operator/kubernetes/operator.yaml"
if [[ -n "${CR_PATCH_YAML}" ]]; then
chectl server:deploy --batch --platform minikube \
--templates "${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH}" \
--che-operator-cr-patch-yaml "${CR_PATCH_YAML}"
else
chectl server:deploy --batch --platform minikube \
--templates "${CURRENT_OPERATOR_VERSION_TEMPLATE_PATH}"
fi
}
pushd ${OPERATOR_REPO} >/dev/null
initDefaults
init "$@"
initTemplates
runTest
popd >/dev/null

View File

@ -34,11 +34,13 @@ unset CATALOG_IMAGE
init() { init() {
unset VERBOSE unset VERBOSE
unset CR_PATCH_YAML
while [[ "$#" -gt 0 ]]; do while [[ "$#" -gt 0 ]]; do
case $1 in case $1 in
'--help'|'-h') usage; exit;; '--help'|'-h') usage; exit;;
'--verbose'|'-v') VERBOSE=1;; '--verbose'|'-v') VERBOSE=1;;
'--cr-patch-yaml') CR_PATCH_YAML=$2; shift 1;;
esac esac
shift 1 shift 1
done done
@ -53,10 +55,11 @@ usage () {
echo "Deploy Eclipse Che from sources" echo "Deploy Eclipse Che from sources"
echo echo
echo "Usage:" echo "Usage:"
echo -e "\t$0 [--verbose]" echo -e "\t$0 [--verbose] [--cr-patch-yaml <path_to_cr_patch>]"
echo echo
echo "OPTIONS:" echo "OPTIONS:"
echo -e "\t-v,--verbose Verbose mode" echo -e "\t-v,--verbose Verbose mode"
echo -e "\t--cr-patch-yaml CheCluster CR patch yaml file"
echo echo
echo "Example:" echo "Example:"
echo -e "\t$0" echo -e "\t$0"
@ -163,8 +166,12 @@ run() {
VERBOSE=${VERBOSE} VERBOSE=${VERBOSE}
make wait-pod-running NAMESPACE="${NAMESPACE}" SELECTOR="app.kubernetes.io/component=che-operator" make wait-pod-running NAMESPACE="${NAMESPACE}" SELECTOR="app.kubernetes.io/component=che-operator"
if [[ $(oc get checluster -n eclipse-che --no-headers | wc -l) == 0 ]]; then if [[ $(oc get checluster -n "${NAMESPACE}" --no-headers | wc -l) == 0 ]]; then
getCheClusterCRFromInstalledCSV | oc apply -n "${NAMESPACE}" -f - getCheClusterCRFromInstalledCSV | oc apply -n "${NAMESPACE}" -f -
if [[ -n ${CR_PATCH_YAML} ]]; then
patch=$(yq -r "." "${CR_PATCH_YAML}" | tr -d "\n" )
oc patch checluster eclipse-che -n "${NAMESPACE}" --type='merge' -p "${patch}"
fi
fi fi
make wait-eclipseche-version VERSION="$(getCheVersionFromInstalledCSV)" NAMESPACE="${NAMESPACE}" VERBOSE=${VERBOSE} make wait-eclipseche-version VERSION="$(getCheVersionFromInstalledCSV)" NAMESPACE="${NAMESPACE}" VERBOSE=${VERBOSE}
} }

View File

@ -77,7 +77,7 @@ metadata:
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
repository: https://github.com/eclipse-che/che-operator repository: https://github.com/eclipse-che/che-operator
support: Eclipse Foundation support: Eclipse Foundation
name: eclipse-che.v7.78.0-817.next name: eclipse-che.v7.78.0-826.next
namespace: placeholder namespace: placeholder
spec: spec:
apiservicedefinitions: {} apiservicedefinitions: {}
@ -527,6 +527,12 @@ spec:
verbs: verbs:
- list - list
- delete - delete
- apiGroups:
- user.openshift.io
resources:
- groups
verbs:
- get
- apiGroups: - apiGroups:
- user.openshift.io - user.openshift.io
resources: resources:
@ -1234,7 +1240,7 @@ spec:
minKubeVersion: 1.19.0 minKubeVersion: 1.19.0
provider: provider:
name: Eclipse Foundation name: Eclipse Foundation
version: 7.78.0-817.next version: 7.78.0-826.next
webhookdefinitions: webhookdefinitions:
- admissionReviewVersions: - admissionReviewVersions:
- v1 - v1

View File

@ -7917,6 +7917,40 @@ spec:
component: che-gateway-config component: che-gateway-config
description: Authentication settings. description: Authentication settings.
properties: properties:
advancedAuthorization:
description: Advance authorization settings. Determines
which users and groups are allowed to access Che. User
is allowed to access Che if he/she is either in the `allowUsers`
list or is member of group from `allowGroups` list and
not in neither the `denyUsers` list nor is member of group
from `denyGroups` list. If `allowUsers` and `allowGroups`
are empty, then all users are allowed to access Che. if
`denyUsers` and `denyGroups` are empty, then no users
are denied to access Che.
properties:
allowGroups:
description: List of groups allowed to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
allowUsers:
description: List of users allowed to access Che.
items:
type: string
type: array
denyGroups:
description: List of groups denied to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
denyUsers:
description: List of users denied to access Che.
items:
type: string
type: array
type: object
gateway: gateway:
default: default:
configLabels: configLabels:

View File

@ -7709,6 +7709,40 @@ spec:
component: che-gateway-config component: che-gateway-config
description: Authentication settings. description: Authentication settings.
properties: properties:
advancedAuthorization:
description: Advance authorization settings. Determines which
users and groups are allowed to access Che. User is allowed
to access Che if he/she is either in the `allowUsers` list
or is member of group from `allowGroups` list and not in
neither the `denyUsers` list nor is member of group from
`denyGroups` list. If `allowUsers` and `allowGroups` are
empty, then all users are allowed to access Che. if `denyUsers`
and `denyGroups` are empty, then no users are denied to
access Che.
properties:
allowGroups:
description: List of groups allowed to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
allowUsers:
description: List of users allowed to access Che.
items:
type: string
type: array
denyGroups:
description: List of groups denied to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
denyUsers:
description: List of users denied to access Che.
items:
type: string
type: array
type: object
gateway: gateway:
default: default:
configLabels: configLabels:

View File

@ -64,6 +64,12 @@ rules:
verbs: verbs:
- list - list
- delete - delete
- apiGroups:
- user.openshift.io
resources:
- groups
verbs:
- get
- apiGroups: - apiGroups:
- user.openshift.io - user.openshift.io
resources: resources:

View File

@ -7728,6 +7728,40 @@ spec:
component: che-gateway-config component: che-gateway-config
description: Authentication settings. description: Authentication settings.
properties: properties:
advancedAuthorization:
description: Advance authorization settings. Determines which
users and groups are allowed to access Che. User is allowed
to access Che if he/she is either in the `allowUsers` list
or is member of group from `allowGroups` list and not in
neither the `denyUsers` list nor is member of group from
`denyGroups` list. If `allowUsers` and `allowGroups` are
empty, then all users are allowed to access Che. if `denyUsers`
and `denyGroups` are empty, then no users are denied to
access Che.
properties:
allowGroups:
description: List of groups allowed to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
allowUsers:
description: List of users allowed to access Che.
items:
type: string
type: array
denyGroups:
description: List of groups denied to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
denyUsers:
description: List of users denied to access Che.
items:
type: string
type: array
type: object
gateway: gateway:
default: default:
configLabels: configLabels:
@ -8432,6 +8466,12 @@ rules:
verbs: verbs:
- list - list
- delete - delete
- apiGroups:
- user.openshift.io
resources:
- groups
verbs:
- get
- apiGroups: - apiGroups:
- user.openshift.io - user.openshift.io
resources: resources:

View File

@ -64,6 +64,12 @@ rules:
verbs: verbs:
- list - list
- delete - delete
- apiGroups:
- user.openshift.io
resources:
- groups
verbs:
- get
- apiGroups: - apiGroups:
- user.openshift.io - user.openshift.io
resources: resources:

View File

@ -7723,6 +7723,40 @@ spec:
component: che-gateway-config component: che-gateway-config
description: Authentication settings. description: Authentication settings.
properties: properties:
advancedAuthorization:
description: Advance authorization settings. Determines which
users and groups are allowed to access Che. User is allowed
to access Che if he/she is either in the `allowUsers` list
or is member of group from `allowGroups` list and not in
neither the `denyUsers` list nor is member of group from
`denyGroups` list. If `allowUsers` and `allowGroups` are
empty, then all users are allowed to access Che. if `denyUsers`
and `denyGroups` are empty, then no users are denied to
access Che.
properties:
allowGroups:
description: List of groups allowed to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
allowUsers:
description: List of users allowed to access Che.
items:
type: string
type: array
denyGroups:
description: List of groups denied to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
denyUsers:
description: List of users denied to access Che.
items:
type: string
type: array
type: object
gateway: gateway:
default: default:
configLabels: configLabels:

View File

@ -7728,6 +7728,40 @@ spec:
component: che-gateway-config component: che-gateway-config
description: Authentication settings. description: Authentication settings.
properties: properties:
advancedAuthorization:
description: Advance authorization settings. Determines which
users and groups are allowed to access Che. User is allowed
to access Che if he/she is either in the `allowUsers` list
or is member of group from `allowGroups` list and not in
neither the `denyUsers` list nor is member of group from
`denyGroups` list. If `allowUsers` and `allowGroups` are
empty, then all users are allowed to access Che. if `denyUsers`
and `denyGroups` are empty, then no users are denied to
access Che.
properties:
allowGroups:
description: List of groups allowed to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
allowUsers:
description: List of users allowed to access Che.
items:
type: string
type: array
denyGroups:
description: List of groups denied to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
denyUsers:
description: List of users denied to access Che.
items:
type: string
type: array
type: object
gateway: gateway:
default: default:
configLabels: configLabels:
@ -8432,6 +8466,12 @@ rules:
verbs: verbs:
- list - list
- delete - delete
- apiGroups:
- user.openshift.io
resources:
- groups
verbs:
- get
- apiGroups: - apiGroups:
- user.openshift.io - user.openshift.io
resources: resources:

View File

@ -64,6 +64,12 @@ rules:
verbs: verbs:
- list - list
- delete - delete
- apiGroups:
- user.openshift.io
resources:
- groups
verbs:
- get
- apiGroups: - apiGroups:
- user.openshift.io - user.openshift.io
resources: resources:

View File

@ -7723,6 +7723,40 @@ spec:
component: che-gateway-config component: che-gateway-config
description: Authentication settings. description: Authentication settings.
properties: properties:
advancedAuthorization:
description: Advance authorization settings. Determines which
users and groups are allowed to access Che. User is allowed
to access Che if he/she is either in the `allowUsers` list
or is member of group from `allowGroups` list and not in
neither the `denyUsers` list nor is member of group from
`denyGroups` list. If `allowUsers` and `allowGroups` are
empty, then all users are allowed to access Che. if `denyUsers`
and `denyGroups` are empty, then no users are denied to
access Che.
properties:
allowGroups:
description: List of groups allowed to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
allowUsers:
description: List of users allowed to access Che.
items:
type: string
type: array
denyGroups:
description: List of groups denied to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
denyUsers:
description: List of users denied to access Che.
items:
type: string
type: array
type: object
gateway: gateway:
default: default:
configLabels: configLabels:

View File

@ -7723,6 +7723,40 @@ spec:
component: che-gateway-config component: che-gateway-config
description: Authentication settings. description: Authentication settings.
properties: properties:
advancedAuthorization:
description: Advance authorization settings. Determines which
users and groups are allowed to access Che. User is allowed
to access Che if he/she is either in the `allowUsers` list
or is member of group from `allowGroups` list and not in
neither the `denyUsers` list nor is member of group from
`denyGroups` list. If `allowUsers` and `allowGroups` are
empty, then all users are allowed to access Che. if `denyUsers`
and `denyGroups` are empty, then no users are denied to
access Che.
properties:
allowGroups:
description: List of groups allowed to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
allowUsers:
description: List of users allowed to access Che.
items:
type: string
type: array
denyGroups:
description: List of groups denied to access Che (currently
supported in OpenShift only).
items:
type: string
type: array
denyUsers:
description: List of users denied to access Che.
items:
type: string
type: array
type: object
gateway: gateway:
default: default:
configLabels: configLabels:

View File

@ -64,6 +64,12 @@ rules:
verbs: verbs:
- list - list
- delete - delete
- apiGroups:
- user.openshift.io
resources:
- groups
verbs:
- get
- apiGroups: - apiGroups:
- user.openshift.io - user.openshift.io
resources: resources:

View File

@ -28,18 +28,18 @@ import (
) )
const ( const (
commonPermissionsTemplateName = "%s-cheworkspaces-clusterrole" userCommonPermissionsTemplateName = "%s-cheworkspaces-clusterrole"
namespacePermissionsTemplateName = "%s-cheworkspaces-namespaces-clusterrole" userDevWorkspacePermissionsTemplateName = "%s-cheworkspaces-devworkspace-clusterrole"
devWorkspacePermissionsTemplateName = "%s-cheworkspaces-devworkspace-clusterrole" cheSASpecificPermissionsTemplateName = "%s-cheworkspaces-namespaces-clusterrole"
) )
// Create ClusterRole and ClusterRoleBinding for "che" service account. // Create ClusterRole and ClusterRoleBinding for "che" service account.
// che-server uses "che" service account for creation RBAC for a user in his namespace. // che-server uses "che" service account for creation RBAC for a user in his namespace.
func (s *CheServerReconciler) syncPermissions(ctx *chetypes.DeployContext) (bool, error) { func (s *CheServerReconciler) syncPermissions(ctx *chetypes.DeployContext) (bool, error) {
policies := map[string][]rbacv1.PolicyRule{ policies := map[string][]rbacv1.PolicyRule{
fmt.Sprintf(commonPermissionsTemplateName, ctx.CheCluster.Namespace): s.getCommonPolicies(), fmt.Sprintf(userCommonPermissionsTemplateName, ctx.CheCluster.Namespace): s.getUserCommonPolicies(),
fmt.Sprintf(namespacePermissionsTemplateName, ctx.CheCluster.Namespace): s.getNamespaceEditorPolicies(), fmt.Sprintf(cheSASpecificPermissionsTemplateName, ctx.CheCluster.Namespace): s.getCheSASpecificPolicies(),
fmt.Sprintf(devWorkspacePermissionsTemplateName, ctx.CheCluster.Namespace): s.getDevWorkspacePolicies(), fmt.Sprintf(userDevWorkspacePermissionsTemplateName, ctx.CheCluster.Namespace): s.getUserDevWorkspacePolicies(),
} }
for name, policy := range policies { for name, policy := range policies {
@ -87,9 +87,9 @@ func (s *CheServerReconciler) syncPermissions(ctx *chetypes.DeployContext) (bool
func (s *CheServerReconciler) deletePermissions(ctx *chetypes.DeployContext) bool { func (s *CheServerReconciler) deletePermissions(ctx *chetypes.DeployContext) bool {
names := []string{ names := []string{
fmt.Sprintf(commonPermissionsTemplateName, ctx.CheCluster.Namespace), fmt.Sprintf(userCommonPermissionsTemplateName, ctx.CheCluster.Namespace),
fmt.Sprintf(namespacePermissionsTemplateName, ctx.CheCluster.Namespace), fmt.Sprintf(cheSASpecificPermissionsTemplateName, ctx.CheCluster.Namespace),
fmt.Sprintf(devWorkspacePermissionsTemplateName, ctx.CheCluster.Namespace), fmt.Sprintf(userDevWorkspacePermissionsTemplateName, ctx.CheCluster.Namespace),
} }
done := true done := true
@ -126,7 +126,7 @@ func (s *CheServerReconciler) deletePermissions(ctx *chetypes.DeployContext) boo
return done return done
} }
func (s *CheServerReconciler) getDevWorkspacePolicies() []rbacv1.PolicyRule { func (s *CheServerReconciler) getUserDevWorkspacePolicies() []rbacv1.PolicyRule {
k8sPolicies := []rbacv1.PolicyRule{ k8sPolicies := []rbacv1.PolicyRule{
{ {
APIGroups: []string{"workspace.devfile.io"}, APIGroups: []string{"workspace.devfile.io"},
@ -138,13 +138,28 @@ func (s *CheServerReconciler) getDevWorkspacePolicies() []rbacv1.PolicyRule {
return k8sPolicies return k8sPolicies
} }
func (s *CheServerReconciler) getNamespaceEditorPolicies() []rbacv1.PolicyRule { func (s *CheServerReconciler) getCheSASpecificPolicies() []rbacv1.PolicyRule {
k8sPolicies := []rbacv1.PolicyRule{ k8sPolicies := []rbacv1.PolicyRule{
{ {
APIGroups: []string{""}, APIGroups: []string{""},
Resources: []string{"namespaces"}, Resources: []string{"namespaces"},
Verbs: []string{"get", "create", "update", "list"}, Verbs: []string{"get", "create", "update", "list"},
}, },
{
APIGroups: []string{""},
Resources: []string{"serviceaccounts"},
Verbs: []string{"get", "watch", "create"},
},
{
APIGroups: []string{"rbac.authorization.k8s.io"},
Resources: []string{"roles"},
Verbs: []string{"get", "create", "update"},
},
{
APIGroups: []string{"rbac.authorization.k8s.io"},
Resources: []string{"rolebindings"},
Verbs: []string{"get", "create", "update", "delete"},
},
} }
openshiftPolicies := []rbacv1.PolicyRule{ openshiftPolicies := []rbacv1.PolicyRule{
@ -158,6 +173,21 @@ func (s *CheServerReconciler) getNamespaceEditorPolicies() []rbacv1.PolicyRule {
Resources: []string{"projects"}, Resources: []string{"projects"},
Verbs: []string{"get", "list"}, Verbs: []string{"get", "list"},
}, },
{
APIGroups: []string{"user.openshift.io"},
Resources: []string{"groups"},
Verbs: []string{"get"},
},
{
APIGroups: []string{"authorization.openshift.io"},
Resources: []string{"roles"},
Verbs: []string{"get", "create", "update"},
},
{
APIGroups: []string{"authorization.openshift.io"},
Resources: []string{"rolebindings"},
Verbs: []string{"get", "create", "update", "delete"},
},
} }
if infrastructure.IsOpenShift() { if infrastructure.IsOpenShift() {
@ -166,13 +196,8 @@ func (s *CheServerReconciler) getNamespaceEditorPolicies() []rbacv1.PolicyRule {
return k8sPolicies return k8sPolicies
} }
func (s *CheServerReconciler) getCommonPolicies() []rbacv1.PolicyRule { func (s *CheServerReconciler) getUserCommonPolicies() []rbacv1.PolicyRule {
k8sPolicies := []rbacv1.PolicyRule{ k8sPolicies := []rbacv1.PolicyRule{
{
APIGroups: []string{""},
Resources: []string{"serviceaccounts"},
Verbs: []string{"get", "watch", "create"},
},
{ {
APIGroups: []string{""}, APIGroups: []string{""},
Resources: []string{"pods/exec"}, Resources: []string{"pods/exec"},
@ -238,16 +263,6 @@ func (s *CheServerReconciler) getCommonPolicies() []rbacv1.PolicyRule {
Resources: []string{"ingresses"}, Resources: []string{"ingresses"},
Verbs: []string{"get", "list", "watch", "create", "delete"}, Verbs: []string{"get", "list", "watch", "create", "delete"},
}, },
{
APIGroups: []string{"rbac.authorization.k8s.io"},
Resources: []string{"roles"},
Verbs: []string{"get", "create", "update"},
},
{
APIGroups: []string{"rbac.authorization.k8s.io"},
Resources: []string{"rolebindings"},
Verbs: []string{"get", "create", "update"},
},
{ {
APIGroups: []string{"metrics.k8s.io"}, APIGroups: []string{"metrics.k8s.io"},
Resources: []string{"pods", "nodes"}, Resources: []string{"pods", "nodes"},
@ -270,16 +285,6 @@ func (s *CheServerReconciler) getCommonPolicies() []rbacv1.PolicyRule {
Resources: []string{"routes"}, Resources: []string{"routes"},
Verbs: []string{"get", "list", "create", "delete"}, Verbs: []string{"get", "list", "create", "delete"},
}, },
{
APIGroups: []string{"authorization.openshift.io"},
Resources: []string{"roles"},
Verbs: []string{"get", "create", "update"},
},
{
APIGroups: []string{"authorization.openshift.io"},
Resources: []string{"rolebindings"},
Verbs: []string{"get", "create", "update"},
},
{ {
APIGroups: []string{"project.openshift.io"}, APIGroups: []string{"project.openshift.io"},
Resources: []string{"projects"}, Resources: []string{"projects"},
@ -293,9 +298,9 @@ func (s *CheServerReconciler) getCommonPolicies() []rbacv1.PolicyRule {
return k8sPolicies return k8sPolicies
} }
func (s *CheServerReconciler) getUserClusterRoles(ctx *chetypes.DeployContext) []string { func (s *CheServerReconciler) getDefaultUserClusterRoles(ctx *chetypes.DeployContext) []string {
return []string{ return []string{
fmt.Sprintf(commonPermissionsTemplateName, ctx.CheCluster.Namespace), fmt.Sprintf(userCommonPermissionsTemplateName, ctx.CheCluster.Namespace),
fmt.Sprintf(devWorkspacePermissionsTemplateName, ctx.CheCluster.Namespace), fmt.Sprintf(userDevWorkspacePermissionsTemplateName, ctx.CheCluster.Namespace),
} }
} }

View File

@ -68,9 +68,9 @@ func TestSyncPermissions(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
names := []string{ names := []string{
fmt.Sprintf(commonPermissionsTemplateName, ctx.CheCluster.Namespace), fmt.Sprintf(userCommonPermissionsTemplateName, ctx.CheCluster.Namespace),
fmt.Sprintf(namespacePermissionsTemplateName, ctx.CheCluster.Namespace), fmt.Sprintf(cheSASpecificPermissionsTemplateName, ctx.CheCluster.Namespace),
fmt.Sprintf(devWorkspacePermissionsTemplateName, ctx.CheCluster.Namespace), fmt.Sprintf(userDevWorkspacePermissionsTemplateName, ctx.CheCluster.Namespace),
} }
for _, name := range names { for _, name := range names {

View File

@ -219,6 +219,14 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *chetypes.DeployContext) (
} }
err = json.Unmarshal(out, &cheEnv) err = json.Unmarshal(out, &cheEnv)
// Advanced authorization
if ctx.CheCluster.Spec.Networking.Auth.AdvancedAuthorization != nil {
cheEnv["CHE_INFRA_KUBERNETES_ADVANCED__AUTHORIZATION_ALLOW__USERS"] = strings.Join(ctx.CheCluster.Spec.Networking.Auth.AdvancedAuthorization.AllowUsers, ",")
cheEnv["CHE_INFRA_KUBERNETES_ADVANCED__AUTHORIZATION_ALLOW__GROUPS"] = strings.Join(ctx.CheCluster.Spec.Networking.Auth.AdvancedAuthorization.AllowGroups, ",")
cheEnv["CHE_INFRA_KUBERNETES_ADVANCED__AUTHORIZATION_DENY__USERS"] = strings.Join(ctx.CheCluster.Spec.Networking.Auth.AdvancedAuthorization.DenyUsers, ",")
cheEnv["CHE_INFRA_KUBERNETES_ADVANCED__AUTHORIZATION_DENY__GROUPS"] = strings.Join(ctx.CheCluster.Spec.Networking.Auth.AdvancedAuthorization.DenyGroups, ",")
}
// k8s specific envs // k8s specific envs
if !infrastructure.IsOpenShift() { if !infrastructure.IsOpenShift() {
k8sCheEnv := map[string]string{ k8sCheEnv := map[string]string{
@ -298,7 +306,7 @@ func GetCheConfigMapVersion(deployContext *chetypes.DeployContext) string {
} }
func (s *CheServerReconciler) updateUserClusterRoles(ctx *chetypes.DeployContext, cheEnv map[string]string) { func (s *CheServerReconciler) updateUserClusterRoles(ctx *chetypes.DeployContext, cheEnv map[string]string) {
userClusterRoles := strings.Join(s.getUserClusterRoles(ctx), ", ") userClusterRoles := strings.Join(s.getDefaultUserClusterRoles(ctx), ", ")
for _, role := range strings.Split(cheEnv["CHE_INFRA_KUBERNETES_USER__CLUSTER__ROLES"], ",") { for _, role := range strings.Split(cheEnv["CHE_INFRA_KUBERNETES_USER__CLUSTER__ROLES"], ",") {
role := strings.TrimSpace(role) role := strings.TrimSpace(role)

View File

@ -55,7 +55,7 @@ func (s *CheServerReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.
} }
if done, err := s.syncPermissions(ctx); !done { if done, err := s.syncPermissions(ctx); !done {
return reconcile.Result{}, false, err return reconcile.Result{Requeue: true}, false, err
} }
done, err = s.syncDeployment(ctx) done, err = s.syncDeployment(ctx)