Merge branch 'main' of github.com:eclipse-che/che-server into github-server-fix

pull/618/head
ivinokur 2024-01-08 16:57:23 +02:00
commit ddb0e29d01
166 changed files with 1485 additions and 344 deletions

View File

@ -17,7 +17,7 @@ USER 0
# Install yq, kubectl, chectl cli used by olm/olm.sh script.
# hadolint ignore=DL3041
RUN dnf install -y -q --allowerasing --nobest nodejs-devel nodejs-libs psmisc python3-pip jq golang httpd-tools \
RUN dnf install -y -q --allowerasing --nobest nodejs-devel nodejs-libs psmisc python3-pip jq yq golang httpd-tools \
# already installed or installed as deps:
openssl openssl-devel ca-certificates make cmake cpp gcc gcc-c++ zlib zlib-devel brotli brotli-devel python3 nodejs-packaging && \
dnf update -y && dnf clean all && \

19
.ci/openshift-ci/ca.crt Normal file
View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDDDCCAfSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtpbmdy
ZXNzLW9wZXJhdG9yQDE3MDI5MTczMzkwHhcNMjMxMjE4MTYzNTM4WhcNMjUxMjE3
MTYzNTM5WjAmMSQwIgYDVQQDDBtpbmdyZXNzLW9wZXJhdG9yQDE3MDI5MTczMzkw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDVfcIyqKLYcrmieDOCvAq
RKFR0PXqjl54DyfhkP7TC/rA4WMaJgYamYNNRcy4rOb+i3P1yepeVlXj+4gka41W
fh1QghqDGPpQTF7I8SDhnz3qdQymgSSkrxBWOGgJZRG3Gd50CNeh+ADdNlOxzZhJ
c1HI9/36Zp0M7RHLNwrYzKf/Scrcl3t/Ps4KHKsNtjNygnPSTjGwza5TTTAvGQ+h
3+c+bKJHZp6VFoEpubmBfCG8x+vJwBNI+YauXwti9EqFutnAbOiQ4aOvqQYINngV
OQTOg3xnifnooaR2iZPOtxPLUDMydHP9sDVNGLICpnKcFN6x5JKq1fAuwOAMRMQr
AgMBAAGjRTBDMA4GA1UdDwEB/wQEAwICpDASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
A1UdDgQWBBRQfZkM6C20GT1YiTiS694vRPP2MDANBgkqhkiG9w0BAQsFAAOCAQEA
qd9ug2Bo2s3CG0qjNtk19WYYAuwkEMZU9L/FbSfmPkkOTbrZB71ofZbVan8Dx9/W
SfbkN1eJQNxd7QIDlExKEW2ufJIMCDe6haLHV8x+z3fISHg3wMUCPtadLG/exafy
agfj8PQgnJ1sbA/fKl0rqcVYuIihZ0DdMe28Yj92BFcs5+TXzVYzjyeIGonUZrCR
LtW2CxV7Ngue9pkWGsqQSlRwzp3knYfZxeQLneZcGlsSV4r9LOKIAA/MhBGgpwVc
zrh7L93jajHD1AD0sRdUQp4VVhysXVmMMSAjaLkqHsvSyJp7yKJOmrts6a274qbU
J1E6cXqtfF0NwRo2D9BouQ==
-----END CERTIFICATE-----

View File

@ -32,6 +32,8 @@ export PRIVATE_REPO_WORKSPACE_NAME=${PRIVATE_REPO_WORKSPACE_NAME:-"private-repo-
export PUBLIC_PROJECT_NAME=${PUBLIC_PROJECT_NAME:-"public-repo"}
export PRIVATE_PROJECT_NAME=${PRIVATE_PROJECT_NAME:-"private-repo"}
export YAML_FILE_NAME=${YAML_FILE_NAME:-"devfile.yaml"}
export CUSTOM_CONFIG_MAP_NAME=${CUSTOM_CONFIG_MAP_NAME:-"custom-ca-certificates"}
export GIT_SSL_CONFIG_MAP_NAME=${GIT_SSL_CONFIG_MAP_NAME:-"che-self-signed-cert"}
provisionOpenShiftOAuthUser() {
echo -e "[INFO] Provisioning Openshift OAuth user"
@ -52,18 +54,38 @@ provisionOpenShiftOAuthUser() {
done
}
configureGitSelfSignedCertificate() {
echo "[INFO] Configure self-signed certificate for Git provider"
oc adm new-project ${CHE_NAMESPACE}
oc project ${CHE_NAMESPACE}
echo -e "[INFO] Create ConfigMap with the required TLS certificate"
oc create configmap ${CUSTOM_CONFIG_MAP_NAME} --from-file=.ci/openshift-ci/ca.crt
oc label configmap ${CUSTOM_CONFIG_MAP_NAME} app.kubernetes.io/part-of=che.eclipse.org app.kubernetes.io/component=ca-bundle
echo "[INFO] Create ConfigMap to support Git repositories with self-signed certificates"
oc create configmap ${GIT_SSL_CONFIG_MAP_NAME} --from-file=.ci/openshift-ci/ca.crt --from-literal=githost=$GIT_PROVIDER_URL
oc label configmap ${GIT_SSL_CONFIG_MAP_NAME} app.kubernetes.io/part-of=che.eclipse.org
}
createCustomResourcesFile() {
cat > custom-resources.yaml <<-END
apiVersion: org.eclipse.che/v2
spec:
devEnvironments:
maxNumberOfRunningWorkspacesPerUser: 10000
maxNumberOfRunningWorkspacesPerUser: 10000
END
echo "Generated custom resources file"
cat custom-resources.yaml
}
patchCustomResourcesFile() {
yq -y '.spec.devEnvironments.trustedCerts += {"gitTrustedCertsConfigMapName": "'${GIT_SSL_CONFIG_MAP_NAME}'"}' custom-resources.yaml -i
cat custom-resources.yaml
}
deployChe() {
chectl server:deploy --cheimage=$CHE_SERVER_IMAGE \
--che-operator-cr-patch-yaml=custom-resources.yaml \
@ -101,6 +123,15 @@ testFactoryResolverNoPatOAuth() {
echo "[INFO] Check factory resolver for public repository with NO PAT/OAuth setup"
testFactoryResolverResponse $1 200
echo "[INFO] Check factory resolver for private repository with NO PAT/OAuth setup"
testFactoryResolverResponse $2 500
}
# check that raw devfile url factory resolver returns correct value without any PAT/OAuth setup
testFactoryResolverNoPatOAuthRaw() {
echo "[INFO] Check factory resolver for public repository with NO PAT/OAuth setup"
testFactoryResolverResponse $1 200
echo "[INFO] Check factory resolver for private repository with NO PAT/OAuth setup"
testFactoryResolverResponse $2 400
}
@ -195,6 +226,87 @@ setupSSHKeyPairs() {
oc apply -f ssh-secret.yaml -n ${USER_CHE_NAMESPACE}
}
# Only for GitLab server administrator users
createOAuthApplicationGitLabServer() {
ADMIN_ACCESS_TOKEN=$1
CHE_URL=https://$(oc get route -n ${CHE_NAMESPACE} che -o jsonpath='{.spec.host}')
echo "[INFO] Create OAuth Application"
response=$(curl -k -X POST \
${GIT_PROVIDER_URL}/api/v4/applications \
-H "PRIVATE-TOKEN: ${ADMIN_ACCESS_TOKEN}" \
-d "name=${APPLICATION_NAME}" \
-d "redirect_uri=${CHE_URL}/api/oauth/callback" \
-d "scopes=api write_repository openid")
echo "[INFO] Response of the created OAuth Application"
OAUTH_ID=$(echo "$response" | jq -r '.id')
APPLICATION_ID=$(echo "$response" | jq -r '.application_id')
APPLICATION_SECRET=$(echo "$response" | jq -r '.secret')
echo "[INFO] OAuth ID: ${OAUTH_ID}"
echo "[INFO] Application ID: ${APPLICATION_ID}"
echo "[INFO] Application Secret: ${APPLICATION_SECRET}"
}
# Only for GitLab server administrator users
deleteOAuthApplicationGitLabServer() {
OAUTH_ID=$1
ADMIN_ACCESS_TOKEN=$2
echo "[INFO] Delete OAuth Application"
curl -i -k -X DELETE \
${GIT_PROVIDER_URL}/api/v4/applications/${OAUTH_ID} \
-H "PRIVATE-TOKEN: ${ADMIN_ACCESS_TOKEN}"
}
# Only for GitLab server
revokeAuthorizedOAuthApplication() {
APPLICATION_ID=$1
APPLICATION_SECRET=$2
echo "[INFO] Revoke authorized OAuth application"
oc project ${USER_CHE_NAMESPACE}
OAUTH_TOKEN_NAME=$(oc get secret | grep 'personal-access-token'| awk 'NR==1 { print $1 }')
echo "[INFO] OAuth token name: "$OAUTH_TOKEN_NAME
OAUTH_TOKEN=$(oc get secret $OAUTH_TOKEN_NAME -o jsonpath='{.data.token}' | base64 -d)
echo "[INFO] Oauth token: "$OAUTH_TOKEN
curl -i -k -X POST \
${GIT_PROVIDER_URL}/oauth/revoke \
-d "client_id=${APPLICATION_ID}" \
-d "client_secret=${APPLICATION_SECRET}" \
-d "token=${OAUTH_TOKEN}"
}
# Only for GitLab server
setupOAuthSecret() {
APPLICATION_ID=$1
APPLICATION_SECRET=$2
echo "[INFO] Setup OAuth Secret"
oc login -u=${OCP_ADMIN_USER_NAME} -p=${OCP_LOGIN_PASSWORD} --insecure-skip-tls-verify=false
oc project ${CHE_NAMESPACE}
SERVER_POD=$(oc get pod -l component=che | grep "che" | awk 'NR==1 { print $1 }')
ENCODED_APP_ID=$(echo -n "${APPLICATION_ID}" | base64 -w 0)
ENCODED_APP_SECRET=$(echo -n "${APPLICATION_SECRET}" | base64 -w 0)
cat .ci/openshift-ci/oauth-secret.yaml > oauth-secret.yaml
# patch the oauth-secret.yaml file
sed -i "s#git-provider-url#${GIT_PROVIDER_URL}#g" oauth-secret.yaml
sed -i "s#encoded-application-id#${ENCODED_APP_ID}#g" oauth-secret.yaml
sed -i "s#encoded-application-secret#${ENCODED_APP_SECRET}#g" oauth-secret.yaml
cat oauth-secret.yaml
oc apply -f oauth-secret.yaml -n ${CHE_NAMESPACE}
echo "[INFO] Wait updating deployment after create OAuth secret"
oc wait --for=delete pod/${SERVER_POD} --timeout=120s
}
runTestWorkspaceWithGitRepoUrl() {
WS_NAME=$1
PROJECT_NAME=$2
@ -260,8 +372,46 @@ deleteTestWorkspace() {
oc delete dw ${WS_NAME} -n ${OCP_USER_NAMESPACE}
}
startOAuthFactoryTest() {
CHE_URL=https://$(oc get route -n ${CHE_NAMESPACE} che -o jsonpath='{.spec.host}')
# patch oauth-factory-test.yaml
cat .ci/openshift-ci/pod-oauth-factory-test.yaml > oauth-factory-test.yaml
sed -i "s#CHE_URL#${CHE_URL}#g" oauth-factory-test.yaml
sed -i "s#CHE-NAMESPACE#${CHE_NAMESPACE}#g" oauth-factory-test.yaml
sed -i "s#OCP_USER_NAME#${OCP_NON_ADMIN_USER_NAME}#g" oauth-factory-test.yaml
sed -i "s#OCP_USER_PASSWORD#${OCP_LOGIN_PASSWORD}#g" oauth-factory-test.yaml
sed -i "s#FACTORY_REPO_URL#${PRIVATE_REPO_URL}#g" oauth-factory-test.yaml
sed -i "s#GIT_BRANCH#${GIT_REPO_BRANCH}#g" oauth-factory-test.yaml
sed -i "s#GIT_PROVIDER_TYPE#${GIT_PROVIDER_TYPE}#g" oauth-factory-test.yaml
sed -i "s#GIT_PROVIDER_USER_NAME#${GIT_PROVIDER_LOGIN}#g" oauth-factory-test.yaml
sed -i "s#GIT_PROVIDER_USER_PASSWORD#${GIT_PROVIDER_PASSWORD}#g" oauth-factory-test.yaml
echo "[INFO] Applying the following patched OAuth Factory Test Pod:"
cat oauth-factory-test.yaml
echo "[INFO] --------------------------------------------------"
oc apply -f oauth-factory-test.yaml
# wait for the pod to start
n=0
while [ $n -le 120 ]
do
PHASE=$(oc get pod -n ${CHE_NAMESPACE} ${TEST_POD_NAME} \
--template='{{ .status.phase }}')
if [[ ${PHASE} == "Running" ]]; then
echo "[INFO] Smoke test started successfully."
return
fi
sleep 5
n=$(( n+1 ))
done
echo "[ERROR] Failed to start smoke test."
exit 1
}
# Catch the finish of the job and write logs in artifacts.
catchFinish() {
echo "[INFO] Terminate the process after finish the test script."
local RESULT=$?
killProcessByPort
if [ "$RESULT" != "0" ]; then
@ -278,8 +428,37 @@ collectEclipseCheLogs() {
mkdir -p ${ARTIFACTS_DIR}/che-logs
# Collect all Eclipse Che logs and cluster CR
chectl server:logs -n $CHE_NAMESPACE --directory ${ARTIFACTS_DIR}/che-logs --telemetry off
oc login -u=${OCP_ADMIN_USER_NAME} -p=${OCP_LOGIN_PASSWORD} --insecure-skip-tls-verify=false
oc get checluster -o yaml -n $CHE_NAMESPACE > "${ARTIFACTS_DIR}/che-cluster.yaml"
chectl server:logs -n $CHE_NAMESPACE --directory ${ARTIFACTS_DIR}/che-logs --telemetry off
}
collectLogs() {
echo "[INFO] Waiting until oauth test pod finished"
oc logs -n ${CHE_NAMESPACE} ${TEST_POD_NAME} -c oauth-test -f
sleep 3
# Download artifacts
set +e
echo "[INFO] Collect all Eclipse Che logs and cluster CR."
collectEclipseCheLogs
echo "[INFO] Downloading test report."
mkdir -p ${ARTIFACTS_DIR}/e2e
oc rsync -n ${CHE_NAMESPACE} ${TEST_POD_NAME}:/tmp/e2e/report/ ${ARTIFACTS_DIR}/e2e -c download-reports
oc exec -n ${CHE_NAMESPACE} ${TEST_POD_NAME} -c download-reports -- touch /tmp/done
# Revoke and delete the OAuth application
revokeAuthorizedOAuthApplication ${APPLICATION_ID} ${APPLICATION_SECRET}
deleteOAuthApplicationGitLabServer ${OAUTH_ID} ${ADMIN_ACCESS_TOKEN}
set -e
EXIT_CODE=$(oc logs -n ${CHE_NAMESPACE} ${TEST_POD_NAME} -c oauth-test | grep EXIT_CODE)
if [[ ${EXIT_CODE} != "+ EXIT_CODE=0" ]]; then
echo "[ERROR] Factory OAuth test failed. Job failed."
exit 1
fi
echo "[INFO] Job completed successfully."
}
testCloneGitRepoNoProjectExists() {
@ -317,3 +496,17 @@ setupTestEnvironment() {
forwardPortToService
initUserNamespace ${OCP_USER_NAME}
}
setupTestEnvironmentOAuthFlow() {
ADMIN_ACCESS_TOKEN=$1
APPLICATION_ID=$2
APPLICATION_SECRET=$3
provisionOpenShiftOAuthUser
configureGitSelfSignedCertificate
createCustomResourcesFile
patchCustomResourcesFile
deployChe
createOAuthApplicationGitLabServer ${ADMIN_ACCESS_TOKEN} ${APPLICATION_NAME}
setupOAuthSecret ${APPLICATION_ID} ${APPLICATION_SECRET}
}

View File

@ -0,0 +1,15 @@
kind: Secret
apiVersion: v1
metadata:
name: gitlab-oauth-secret
namespace: eclipse-che
labels:
app.kubernetes.io/part-of: che.eclipse.org
app.kubernetes.io/component: oauth-scm-configuration
annotations:
che.eclipse.org/oauth-scm-server: gitlab
che.eclipse.org/scm-server-endpoint: git-provider-url
type: Opaque
data:
id: encoded-application-id
secret: encoded-application-secret

View File

@ -0,0 +1,89 @@
apiVersion: v1
kind: Pod
metadata:
name: oauth-factory-test
namespace: CHE-NAMESPACE
spec:
volumes:
- name: test-run-results
- name: ffmpeg-video
- name: dshm
emptyDir:
medium: Memory
containers:
# container containing the tests
- name: oauth-test
image: quay.io/eclipse/che-e2e:next
imagePullPolicy: Always
env:
- name: VIDEO_RECORDING
value: "true"
- name: TEST_SUITE
value: "test"
- name: TS_SELENIUM_EDITOR
value: "che-code"
- name: USERSTORY
value: "Factory"
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
- name: TS_SELENIUM_BASE_URL
value: "CHE_URL"
- name: TS_SELENIUM_LOG_LEVEL
value: "TRACE"
- name: TS_SELENIUM_OCP_USERNAME
value: "OCP_USER_NAME"
- name: TS_SELENIUM_OCP_PASSWORD
value: "OCP_USER_PASSWORD"
- name: TS_SELENIUM_VALUE_OPENSHIFT_OAUTH
value: "true"
- name: TS_SELENIUM_FACTORY_GIT_REPO_URL
value: "FACTORY_REPO_URL"
- name: TS_SELENIUM_FACTORY_GIT_REPO_BRANCH
value: "GIT_BRANCH"
- name: TS_SELENIUM_FACTORY_GIT_PROVIDER
value: "GIT_PROVIDER_TYPE"
- name: TS_SELENIUM_GIT_PROVIDER_OAUTH
value: "true"
- name: TS_SELENIUM_GIT_PROVIDER_USERNAME
value: "GIT_PROVIDER_USER_NAME"
- name: TS_SELENIUM_GIT_PROVIDER_PASSWORD
value: "GIT_PROVIDER_USER_PASSWORD"
- name: TS_OCP_LOGIN_PAGE_PROVIDER_TITLE
value: "htpasswd"
- name: DELETE_WORKSPACE_ON_FAILED_TEST
value: "true"
- name: TS_SELENIUM_START_WORKSPACE_TIMEOUT
value: "360000"
- name: TS_IDE_LOAD_TIMEOUT
value: "40000"
volumeMounts:
- name: test-run-results
mountPath: /tmp/e2e/report/
- name: ffmpeg-video
mountPath: /tmp/ffmpeg_report/
- name: dshm
mountPath: /dev/shm
resources:
requests:
memory: "3Gi"
cpu: "2"
limits:
memory: "4Gi"
cpu: "2"
# Download results
- name: download-reports
image: eeacms/rsync
imagePullPolicy: IfNotPresent
volumeMounts:
- name: test-run-results
mountPath: /tmp/e2e/report/
- name: ffmpeg-video
mountPath: /tmp/ffmpeg_report/
resources:
command: ["sh"]
args:
[
"-c",
"while true; if [[ -f /tmp/done ]]; then exit 0; fi; do sleep 1; done",
]
restartPolicy: Never

View File

@ -26,8 +26,7 @@ source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
# due to the issue https://github.com/eclipse/che/issues/22469
# testFactoryResolverNoPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_URL} ${PRIVATE_REPO_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}
testCloneGitRepoNoProjectExists ${PRIVATE_REPO_WORKSPACE_NAME} ${PRIVATE_PROJECT_NAME} ${PRIVATE_REPO_URL} ${USER_CHE_NAMESPACE}

View File

@ -26,7 +26,7 @@ source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testFactoryResolverNoPatOAuthRaw ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -26,7 +26,7 @@ source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testFactoryResolverNoPatOAuthRaw ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testCloneGitRepoNoProjectExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -26,7 +26,7 @@ source "${SCRIPT_DIR}"/common.sh
trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
testFactoryResolverNoPatOAuth ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testFactoryResolverNoPatOAuthRaw ${PUBLIC_REPO_RAW_PATH_URL} ${PRIVATE_REPO_RAW_PATH_URL}
testCloneGitRepoNoProjectExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_RAW_PATH_URL} ${USER_CHE_NAMESPACE}
deleteTestWorkspace ${PUBLIC_REPO_WORKSPACE_NAME} ${USER_CHE_NAMESPACE}

View File

@ -0,0 +1,37 @@
#!/bin/bash
#
# Copyright (c) 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
#
# exit immediately when a command fails
set -ex
# only exit with zero if all commands of the pipeline exit successfully
set -o pipefail
export TEST_POD_NAME=${TEST_POD_NAME:-"oauth-factory-test"}
export GIT_PROVIDER_TYPE=${GIT_PROVIDER_TYPE:-"gitlab"}
export GIT_PROVIDER_URL=${GIT_PROVIDER_URL:-"https://gitlab-gitlab-system.apps.git.crw-qe.com"}
export GIT_PROVIDER_LOGIN=${GIT_PROVIDER_LOGIN:-"admin-user"}
export PRIVATE_REPO_URL=${PRIVATE_REPO_URL:-"https://gitlab-gitlab-system.apps.git.crw-qe.com/admin-user/private-repo.git"}
export GIT_REPO_BRANCH=${PRIVATE_REPO_BRANCH:-"main"}
export APPLICATION_NAME=${APPLICATION_NAME:-"TestApp"}
export OAUTH_ID=""
export APPLICATION_ID=""
export APPLICATION_SECRET=""
# import common test functions
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source "${SCRIPT_DIR}"/common.sh
trap "collectLogs" EXIT SIGINT
setupTestEnvironmentOAuthFlow ${ADMIN_ACCESS_TOKEN} ${APPLICATION_NAME} ${APPLICATION_ID} ${APPLICATION_SECRET}
startOAuthFactoryTest

View File

@ -31,23 +31,23 @@ jobs:
cache: 'maven'
- name: Login to docker.io
if: github.event_name == 'pull_request'
uses: docker/login-action@v2
uses: redhat-actions/podman-login@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
registry: docker.io
- name: Login to quay.io
if: github.event_name == 'pull_request'
uses: docker/login-action@v2
uses: redhat-actions/podman-login@v1
with:
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_PASSWORD }}
registry: quay.io
- name: Build with Maven
run: mvn -B clean install -U -Pintegration
- name: Build docker images
- name: Build images
if: github.event_name == 'pull_request'
run: ./build/build.sh --tag:${{ env.PR_IMAGE_TAG }}
- name: Push docker images
- name: Push images
if: github.event_name == 'pull_request'
run: docker push quay.io/eclipse/che-server:${{ env.PR_IMAGE_TAG }}
run: podman push quay.io/eclipse/che-server:${{ env.PR_IMAGE_TAG }}

View File

@ -29,28 +29,28 @@ jobs:
java-version: '11'
cache: 'maven'
- name: Login to docker.io
uses: docker/login-action@v2
uses: redhat-actions/podman-login@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
registry: docker.io
- name: Login to quay.io
uses: docker/login-action@v2
uses: redhat-actions/podman-login@v1
with:
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_PASSWORD }}
registry: quay.io
- name: Build with Maven
run: mvn -B clean install -U -Pintegration
- name: Build docker images
- name: Build images
id: build
run: |
echo "short_sha1=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
./build/build.sh --tag:next --sha-tag
- name: Push docker images
run: |
docker push quay.io/eclipse/che-server:next
docker push quay.io/eclipse/che-server:${{ steps.build.outputs.short_sha1 }}
podman push quay.io/eclipse/che-server:next
podman push quay.io/eclipse/che-server:${{ steps.build.outputs.short_sha1 }}
- name: Create failure MM message
if: ${{ failure() }}
run: |

View File

@ -32,3 +32,7 @@ Other modules are deprecated and will be removed in the future.
The Eclipse Che community is globally reachable through public chat rooms, mailing list and weekly calls.
See the Eclipse Che Documentation about [how you can join our community](https://www.eclipse.org/che/docs/stable/overview/introduction-to-eclipse-che/#_joining_the_community).
## Builds
* [![release latest stable](https://github.com/eclipse-che/che-server/actions/workflows/release.yml/badge.svg)](https://github.com/eclipse-che/che-server/actions/workflows/release.yml)

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-che-tomcat</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-main</artifactId>
<packaging>pom</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-root-war</artifactId>
<packaging>war</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-swagger-war</artifactId>
<packaging>war</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-assembly-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>assembly-wsmaster-war</artifactId>
<packaging>war</packaging>

View File

@ -663,3 +663,16 @@ che.oauth2.gitlab.clientid_filepath=NULL
# Location of the file with GitLab client secret.
che.oauth2.gitlab.clientsecret_filepath=NULL
### Advanced authorization
# Comma separated list of users allowed to access Che.
che.infra.kubernetes.advanced_authorization.allow_users=NULL
# Comma separated list of groups of users allowed to access Che.
che.infra.kubernetes.advanced_authorization.allow_groups=NULL
# Comma separated list of users denied to access Che.
che.infra.kubernetes.advanced_authorization.deny_users=NULL
# Comma separated list of groups of users denied to access Che.
che.infra.kubernetes.advanced_authorization.deny_groups=NULL

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-server</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>che-assembly-parent</artifactId>

View File

@ -15,6 +15,7 @@ IMAGE_ALIASES=${IMAGE_ALIASES:-}
ERROR=${ERROR:-}
DIR=${DIR:-}
SHA_TAG=${SHA_TAG:-}
BUILDER=${BUILDER:-}
skip_tests() {
if [ $SKIP_TESTS = "true" ]; then
@ -49,6 +50,7 @@ init() {
ARGS=""
OPTIONS=""
DOCKERFILE=""
BUILD_COMMAND="build"
BUILD_ARGS=""
while [ $# -gt 0 ]; do
@ -104,6 +106,37 @@ build() {
DIR=$(cd "$(dirname "$0")"; pwd)
fi
BUILD_COMAMAND="build"
if [ -z $BUILDER ]; then
echo "BUILDER is not specified, trying with podman"
BUILDER=$(command -v podman || true)
if [[ ! -x $BUILDER ]]; then
echo "[WARNING] podman is not installed, trying with buildah"
BUILDER=$(command -v buildah || true)
if [[ ! -x $BUILDER ]]; then
echo "[WARNING] buildah is not installed, trying with docker"
BUILDER=$(command -v docker || true)
if [[ ! -x $BUILDER ]]; then
echo "[ERROR] This script requires podman, buildah or docker to be installed. Must abort!"; exit 1
fi
else
BUILD_COMMAND="bud"
fi
fi
else
if [[ ! -x $(command -v "$BUILDER" || true) ]]; then
echo "Builder $BUILDER is missing. Aborting."; exit 1
fi
if [[ $BUILDER =~ "docker" || $BUILDER =~ "podman" ]]; then
if [[ ! $($BUILDER ps) ]]; then
echo "Builder $BUILDER is not functioning. Aborting."; exit 1
fi
fi
if [[ $BUILDER =~ "buildah" ]]; then
BUILD_COMMAND="bud"
fi
fi
# If Dockerfile is empty, build all Dockerfiles
if [ -z ${DOCKERFILE} ]; then
DOCKERFILES_TO_BUILD="$(ls ${DIR}/Dockerfile*)"
@ -138,14 +171,14 @@ build_image() {
-e "s;\${BUILD_PREFIX};${PREFIX};" \
-e "s;\${BUILD_TAG};${TAG};" \
> ${DIR}/.Dockerfile
cd "${DIR}" && docker build -f ${DIR}/.Dockerfile -t ${IMAGE_NAME} ${BUILD_ARGS} .
cd "${DIR}" && "${BUILDER}" "${BUILD_COMMAND}" -f ${DIR}/.Dockerfile -t ${IMAGE_NAME} ${BUILD_ARGS} .
DOCKER_BUILD_STATUS=$?
rm ${DIR}/.Dockerfile
if [ $DOCKER_BUILD_STATUS -eq 0 ]; then
printf "Build of ${BLUE}${IMAGE_NAME} ${GREEN}[OK]${NC}\n"
if [ ! -z "${SHA_TAG}" ]; then
SHA_IMAGE_NAME=${ORGANIZATION}/${PREFIX}-${NAME}:${SHA_TAG}
docker tag ${IMAGE_NAME} ${SHA_IMAGE_NAME}
"${BUILDER}" tag ${IMAGE_NAME} ${SHA_IMAGE_NAME}
DOCKER_TAG_STATUS=$?
if [ $DOCKER_TAG_STATUS -eq 0 ]; then
printf "Re-tagging with SHA based tag ${BLUE}${SHA_IMAGE_NAME} ${GREEN}[OK]${NC}\n"
@ -157,7 +190,7 @@ build_image() {
if [ ! -z "${IMAGE_ALIASES}" ]; then
for TMP_IMAGE_NAME in ${IMAGE_ALIASES}
do
docker tag ${IMAGE_NAME} ${TMP_IMAGE_NAME}:${TAG}
"${BUILDER}" tag ${IMAGE_NAME} ${TMP_IMAGE_NAME}:${TAG}
DOCKER_TAG_STATUS=$?
if [ $DOCKER_TAG_STATUS -eq 0 ]; then
printf " /alias ${BLUE}${TMP_IMAGE_NAME}:${TAG}${NC} ${GREEN}[OK]${NC}\n"
@ -175,32 +208,6 @@ build_image() {
fi
}
check_docker() {
if ! docker ps > /dev/null 2>&1; then
output=$(docker ps)
printf "${RED}Docker not installed properly: ${output}${NC}\n"
exit 1
fi
}
docker_exec() {
if has_docker_for_windows_client; then
MSYS_NO_PATHCONV=1 docker.exe "$@"
else
"$(which docker)" "$@"
fi
}
has_docker_for_windows_client() {
GLOBAL_HOST_ARCH=$(docker version --format {{.Client}})
if [[ "${GLOBAL_HOST_ARCH}" = *"windows"* ]]; then
return 0
else
return 1
fi
}
get_full_path() {
echo "$(cd "$(dirname "${1}")"; pwd)/$(basename "$1")"
}

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-core</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-dto-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-dto</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-model</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-db-vendor-h2</artifactId>
<name>Che Core :: Commons :: DB :: Vendor H2</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-db-vendor-mysql</artifactId>
<name>Che Core :: Commons :: DB :: Vendor MySQL</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-db-vendor-postgresql</artifactId>
<name>Che Core :: Commons :: DB :: Vendor PostgreSQL</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-db</artifactId>
<name>Che Core :: Commons :: DB</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-logback</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-metrics-core</artifactId>
<name>Che Core :: Commons :: Metrics :: Core</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-tracing-core</artifactId>
<name>Che Core :: Commons :: Tracing :: Core</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-tracing-metrics</artifactId>
<name>Che Core :: Commons :: Tracing :: Metrics</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-tracing-web</artifactId>
<name>Che Core :: Commons :: Tracing :: Web</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-typescript-dto-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-annotations</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-inject</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-j2ee</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-json</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-lang</artifactId>
<packaging>jar</packaging>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* Copyright (c) 2012-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/
@ -11,6 +11,13 @@
*/
package org.eclipse.che.commons.lang;
import static com.google.common.base.Strings.isNullOrEmpty;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.Set;
/** Set of useful String methods */
public class StringUtils {
@ -91,4 +98,13 @@ public class StringUtils {
}
return -1;
}
/** Parse string to set of strings. String should be comma separated. Whitespaces are trimmed. */
public static Set<String> strToSet(String str) {
if (!isNullOrEmpty(str)) {
return Sets.newHashSet(Splitter.on(",").trimResults().omitEmptyStrings().split(str));
} else {
return Collections.emptySet();
}
}
}

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-observability</artifactId>
<name>Che Core :: Commons :: Tracing and Monitoring wrapper</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-schedule</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-test</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-commons-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-commons-tracing</artifactId>
<name>Che Core :: Commons :: Tracing</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-core-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>che-core-commons-parent</artifactId>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-server</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.che.core</groupId>

View File

@ -13,13 +13,23 @@ components:
- name: m2
volume: {}
commands:
- id: build
- id: buildsources
exec:
label: "1. Build"
label: "1. Build sources"
component: tools
workingDir: ${PROJECT_SOURCE}
commandLine: |
mvn clean install -DskipTests
mvn clean install -V -e -Pfast -DskipTests -Dskip-validate-sources -Denforcer.skip=true
group:
kind: build
isDefault: true
- id: buildimage
exec:
label: "2. Build image"
component: tools
workingDir: ${PROJECT_SOURCE}
commandLine: |
./build/build.sh
group:
kind: build
isDefault: true

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-infrastructures-parent</artifactId>
<groupId>org.eclipse.che.infrastructure</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>infrastructure-distributed</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-infrastructures-parent</artifactId>
<groupId>org.eclipse.che.infrastructure</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>infrastructure-factory</artifactId>
<packaging>jar</packaging>

View File

@ -90,7 +90,10 @@ public class KubernetesAuthorisationRequestManager implements AuthorisationReque
Map<String, List<String>> params = getQueryParametersFromState(getState(requestUrl));
errorValues = errorValues == null ? uriInfo.getQueryParameters().get("error") : errorValues;
if (errorValues != null && errorValues.contains("access_denied")) {
store(getParameter(params, "oauth_provider"));
String oauthProvider = getParameter(params, "oauth_provider");
if (!isNullOrEmpty(oauthProvider)) {
store(oauthProvider);
}
}
}

View File

@ -23,6 +23,7 @@ import static org.eclipse.che.workspace.infrastructure.kubernetes.provision.secr
import static org.eclipse.che.workspace.infrastructure.kubernetes.provision.secret.KubernetesSecretAnnotationNames.DEV_WORKSPACE_PREFIX;
import com.google.common.collect.ImmutableMap;
import com.google.common.net.PercentEscaper;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Secret;
@ -173,10 +174,12 @@ public class KubernetesGitCredentialManager implements GitCredentialManager {
* field.
*/
private String getUsernameSegment(PersonalAccessToken personalAccessToken) {
// Special characters are not allowed in URL username segment, so we need to escape them.
PercentEscaper percentEscaper = new PercentEscaper("", false);
return personalAccessToken.getScmTokenName().startsWith(OAUTH_2_PREFIX)
? "oauth2"
: isNullOrEmpty(personalAccessToken.getScmOrganization())
? personalAccessToken.getScmUserName()
? percentEscaper.escape(personalAccessToken.getScmUserName())
: "username";
}

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-infrastructures-parent</artifactId>
<groupId>org.eclipse.che.infrastructure</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>infrastructure-metrics</artifactId>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-infrastructures-parent</artifactId>
<groupId>org.eclipse.che.infrastructure</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>infrastructure-permission</artifactId>
<name>Infrastructure :: Kubernetes Permissions</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-infrastructures-parent</artifactId>
<groupId>org.eclipse.che.infrastructure</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>infrastructure-kubernetes</artifactId>
<name>Infrastructure :: Kubernetes</name>

View File

@ -36,6 +36,9 @@ import org.eclipse.che.api.workspace.server.spi.provision.env.CheApiInternalEnvV
import org.eclipse.che.api.workspace.server.wsplugins.ChePluginsApplier;
import org.eclipse.che.api.workspace.shared.Constants;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.KubernetesNamespaceService;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.AuthorizationChecker;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.KubernetesAuthorizationCheckerImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.PermissionsCleaner;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.jpa.JpaKubernetesRuntimeCacheModule;
import org.eclipse.che.workspace.infrastructure.kubernetes.devfile.DockerimageComponentToWorkspaceApplier;
import org.eclipse.che.workspace.infrastructure.kubernetes.devfile.KubernetesComponentToWorkspaceApplier;
@ -110,6 +113,9 @@ public class KubernetesInfraModule extends AbstractModule {
namespaceConfigurators.addBinding().to(SshKeysConfigurator.class);
namespaceConfigurators.addBinding().to(GitconfigUserDataConfigurator.class);
bind(AuthorizationChecker.class).to(KubernetesAuthorizationCheckerImpl.class);
bind(PermissionsCleaner.class).asEagerSingleton();
bind(KubernetesNamespaceService.class);
MapBinder<String, InternalEnvironmentFactory> factories =

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2012-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
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.authorization;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
/** This {@link AuthorizationChecker} checks if user is allowed to use Che. */
public interface AuthorizationChecker {
boolean isAuthorized(String username) throws InfrastructureException;
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2012-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
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.authorization;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
/**
* An exception thrown by {@link RuntimeInfrastructure} and related components. Indicates that a
* user is not authorized to use Che.
*
* @author Anatolii Bazko
*/
public class AuthorizationException extends InfrastructureException {
public AuthorizationException(String message) {
super(message);
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2012-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
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.authorization;
import static org.eclipse.che.commons.lang.StringUtils.strToSet;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.eclipse.che.commons.annotation.Nullable;
/** This {@link KubernetesAuthorizationCheckerImpl} checks if user is allowed to use Che. */
@Singleton
public class KubernetesAuthorizationCheckerImpl implements AuthorizationChecker {
private final Set<String> allowUsers;
private final Set<String> denyUsers;
@Inject
public KubernetesAuthorizationCheckerImpl(
@Nullable @Named("che.infra.kubernetes.advanced_authorization.allow_users") String allowUsers,
@Nullable @Named("che.infra.kubernetes.advanced_authorization.deny_users") String denyUsers) {
this.allowUsers = strToSet(allowUsers);
this.denyUsers = strToSet(denyUsers);
}
public boolean isAuthorized(String username) {
return isAllowedUser(username) && !isDeniedUser(username);
}
private boolean isAllowedUser(String username) {
return allowUsers.isEmpty() || allowUsers.contains(username);
}
private boolean isDeniedUser(String username) {
return !denyUsers.isEmpty() && denyUsers.contains(username);
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2012-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
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.authorization;
import static org.eclipse.che.commons.lang.StringUtils.strToSet;
import io.fabric8.kubernetes.client.KubernetesClient;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
/** This {@link PermissionsCleaner} cleans up all user's permissions. */
@Singleton
public class PermissionsCleaner {
private final Set<String> userClusterRoles;
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
@Inject
public PermissionsCleaner(
@Nullable @Named("che.infra.kubernetes.user_cluster_roles") String userClusterRoles,
CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
this.userClusterRoles = strToSet(userClusterRoles);
}
public void cleanUp(String namespaceName) throws InfrastructureException {
KubernetesClient client = cheServerKubernetesClientFactory.create();
for (String userClusterRole : userClusterRoles) {
client.rbac().roleBindings().inNamespace(namespaceName).withName(userClusterRole).delete();
}
}
}

View File

@ -57,6 +57,9 @@ import org.eclipse.che.inject.ConfigurationException;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.impls.KubernetesNamespaceMetaImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.AuthorizationChecker;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.AuthorizationException;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.PermissionsCleaner;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.NamespaceConfigurator;
import org.eclipse.che.workspace.infrastructure.kubernetes.util.KubernetesSharedPool;
import org.slf4j.Logger;
@ -98,6 +101,8 @@ public class KubernetesNamespaceFactory {
private final PreferenceManager preferenceManager;
protected final Set<NamespaceConfigurator> namespaceConfigurators;
protected final KubernetesSharedPool sharedPool;
protected final AuthorizationChecker authorizationChecker;
protected final PermissionsCleaner permissionsCleaner;
@Inject
public KubernetesNamespaceFactory(
@ -110,7 +115,9 @@ public class KubernetesNamespaceFactory {
Set<NamespaceConfigurator> namespaceConfigurators,
CheServerKubernetesClientFactory cheServerKubernetesClientFactory,
PreferenceManager preferenceManager,
KubernetesSharedPool sharedPool)
KubernetesSharedPool sharedPool,
AuthorizationChecker authorizationChecker,
PermissionsCleaner permissionsCleaner)
throws ConfigurationException {
this.namespaceCreationAllowed = namespaceCreationAllowed;
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
@ -120,6 +127,8 @@ public class KubernetesNamespaceFactory {
this.labelNamespaces = labelNamespaces;
this.annotateNamespaces = annotateNamespaces;
this.namespaceConfigurators = ImmutableSet.copyOf(namespaceConfigurators);
this.authorizationChecker = authorizationChecker;
this.permissionsCleaner = permissionsCleaner;
//noinspection UnstableApiUsage
Splitter.MapSplitter csvMapSplitter = Splitter.on(",").withKeyValueSeparator("=");
@ -281,6 +290,9 @@ public class KubernetesNamespaceFactory {
var subject = EnvironmentContext.getCurrent().getSubject();
var userName = subject.getUserName();
validateAuthorization(namespace.getName(), userName);
NamespaceResolutionContext resolutionCtx =
new NamespaceResolutionContext(identity.getWorkspaceId(), subject.getUserId(), userName);
Map<String, String> namespaceAnnotationsEvaluated =
@ -573,6 +585,27 @@ public class KubernetesNamespaceFactory {
}
}
protected void validateAuthorization(String namespaceName, String username)
throws InfrastructureException {
if (!authorizationChecker.isAuthorized(username)) {
try {
permissionsCleaner.cleanUp(namespaceName);
} catch (InfrastructureException | KubernetesClientException e) {
LOG.error(
"Failed to clean up permissions for user '{}' in namespace '{}'. Cause: {}",
username,
namespaceName,
e.getMessage(),
e);
}
throw new AuthorizationException(
format(
"User '%s' is not authorized to create a project. Please contact your system administrator.",
username));
}
}
protected String evalPlaceholders(String namespace, NamespaceResolutionContext ctx) {
checkArgument(!isNullOrEmpty(namespace));
String evaluated = namespace;

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2012-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
*/
package org.eclipse.che.workspace.infrastructure.kubernetes.authorization;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
@Listeners(MockitoTestNGListener.class)
public class KubernetesAuthorizationCheckerTest {
@Test(dataProvider = "advancedAuthorizationData")
public void advancedAuthorization(
String testUserName, String allowedUsers, String deniedUsers, boolean expectedIsAuthorized)
throws InfrastructureException {
// give
AuthorizationChecker authorizationChecker =
new KubernetesAuthorizationCheckerImpl(allowedUsers, deniedUsers);
// when
boolean isAuthorized = authorizationChecker.isAuthorized(testUserName);
// then
Assert.assertEquals(isAuthorized, expectedIsAuthorized);
}
@DataProvider
public static Object[][] advancedAuthorizationData() {
return new Object[][] {
{"user1", "", "", true},
{"user1", "user1", "", true},
{"user1", "user1", "user2", true},
{"user1", "user1", "user1", false},
{"user2", "user1", "", false},
{"user2", "user1", "user2", false},
};
}
}

View File

@ -87,6 +87,8 @@ import org.eclipse.che.inject.ConfigurationException;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.impls.KubernetesNamespaceMetaImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.AuthorizationChecker;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.PermissionsCleaner;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.NamespaceConfigurator;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.PreferencesConfigMapConfigurator;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.WorkspaceServiceAccountConfigurator;
@ -126,6 +128,8 @@ public class KubernetesNamespaceFactoryTest {
private KubernetesClient k8sClient;
@Mock private PreferenceManager preferenceManager;
@Mock Appender mockedAppender;
@Mock AuthorizationChecker authorizationChecker;
@Mock PermissionsCleaner permissionsCleaner;
@Mock private NonNamespaceOperation namespaceOperation;
@ -151,6 +155,7 @@ public class KubernetesNamespaceFactoryTest {
lenient().when(namespaceOperation.withName(any())).thenReturn(namespaceResource);
lenient().when(namespaceResource.get()).thenReturn(mock(Namespace.class));
lenient().when(authorizationChecker.isAuthorized(anyString())).thenReturn(true);
lenient().doReturn(namespaceListResource).when(namespaceOperation).withLabels(anyMap());
lenient().when(namespaceListResource.list()).thenReturn(namespaceList);
@ -179,7 +184,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
namespaceFactory.checkIfNamespaceIsAllowed("jondoe-che");
}
@ -204,7 +211,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
namespaceFactory.checkIfNamespaceIsAllowed("any-namespace");
}
@ -222,7 +231,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
assertEquals("che-kube-admin", namespaceFactory.normalizeNamespaceName("kube:admin"));
}
@ -245,7 +256,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
namespaceFactory.checkIfNamespaceIsAllowed("any-namespace");
}
@ -265,7 +278,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
}
@Test
@ -313,7 +328,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));
// when
@ -354,7 +371,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));
// when
@ -382,7 +401,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
// when
namespaceFactory.list();
@ -413,7 +434,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
List<KubernetesNamespaceMeta> availableNamespaces = namespaceFactory.list();
assertEquals(availableNamespaces.size(), 1);
@ -439,7 +462,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
List<KubernetesNamespaceMeta> availableNamespaces = namespaceFactory.list();
assertEquals(availableNamespaces.size(), 1);
@ -467,7 +492,9 @@ public class KubernetesNamespaceFactoryTest {
Set.of(new PreferencesConfigMapConfigurator(cheServerKubernetesClientFactory)),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
when(toReturnNamespace.getName()).thenReturn("namespaceName");
doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any());
@ -508,7 +535,9 @@ public class KubernetesNamespaceFactoryTest {
namespaceConfigurators,
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
@ -543,7 +572,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any());
@ -575,7 +606,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any());
@ -608,7 +641,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
throwOnTryToGetNamespaceByName(
"jondoe-che", new KubernetesClientException("connection refused"));
@ -631,7 +666,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
throwOnTryToGetNamespacesList(new KubernetesClientException("connection refused"));
namespaceFactory.list();
@ -659,7 +696,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any());
@ -688,7 +727,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
doReturn(toReturnNamespace).when(namespaceFactory).doCreateNamespaceAccess(any(), any());
@ -723,7 +764,9 @@ public class KubernetesNamespaceFactoryTest {
Set.of(serviceAccountCfg),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
when(toReturnNamespace.getName()).thenReturn("workspace123");
@ -761,7 +804,9 @@ public class KubernetesNamespaceFactoryTest {
Set.of(serviceAccountConfigurator),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
when(toReturnNamespace.getName()).thenReturn("workspace123");
@ -836,7 +881,9 @@ public class KubernetesNamespaceFactoryTest {
Set.of(serviceAccountConfigurator),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
when(toReturnNamespace.getName()).thenReturn("workspace123");
@ -881,7 +928,9 @@ public class KubernetesNamespaceFactoryTest {
"serviceAccount", "", cheServerKubernetesClientFactory)),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
when(toReturnNamespace.getName()).thenReturn("workspace123");
@ -945,7 +994,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
WorkspaceImpl workspace =
new WorkspaceImplBuilder().setId("workspace123").setAttributes(emptyMap()).build();
@ -968,7 +1019,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
Map<String, String> prefs = new HashMap<>();
prefs.put(WORKSPACE_INFRASTRUCTURE_NAMESPACE_ATTRIBUTE, "che-123");
@ -996,7 +1049,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
Map<String, String> prefs = new HashMap<>();
// returned but ignored
@ -1025,7 +1080,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
Map<String, String> prefs = new HashMap<>();
// returned but ignored
@ -1054,7 +1111,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
doReturn(empty()).when(namespaceFactory).fetchNamespace(anyString());
String namespace =
@ -1079,7 +1138,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
WorkspaceImpl workspace =
new WorkspaceImplBuilder()
@ -1106,7 +1167,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
WorkspaceImpl workspace =
new WorkspaceImplBuilder()
@ -1154,7 +1217,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
String namespace =
namespaceFactory.evaluateNamespaceName(
@ -1178,7 +1243,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
when(toReturnNamespace.getName()).thenReturn("jondoe-che");
@ -1215,7 +1282,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
when(toReturnNamespace.getName()).thenReturn("jondoe-cha-cha-cha");
@ -1251,7 +1320,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
when(toReturnNamespace.getName()).thenReturn("jondoe-cha-cha-cha");
@ -1299,7 +1370,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));
namespaceFactory.list();
@ -1322,7 +1395,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool));
pool,
authorizationChecker,
permissionsCleaner));
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));
KubernetesNamespace toReturnNamespace = mock(KubernetesNamespace.class);
prepareNamespace(toReturnNamespace);
@ -1351,7 +1426,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
assertEquals(expected, namespaceFactory.normalizeNamespaceName(raw));
}
@ -1368,7 +1445,9 @@ public class KubernetesNamespaceFactoryTest {
emptySet(),
cheServerKubernetesClientFactory,
preferenceManager,
pool);
pool,
authorizationChecker,
permissionsCleaner);
assertEquals(
63,

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-infrastructures-parent</artifactId>
<groupId>org.eclipse.che.infrastructure</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>infrastructure-openshift</artifactId>
<name>Infrastructure :: OpenShift</name>
@ -161,6 +161,17 @@
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-server-mock</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>junit-jupiter-api</artifactId>
<groupId>org.junit.jupiter</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>openshift-server-mock</artifactId>

View File

@ -40,6 +40,8 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientTermi
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesEnvironmentProvisioner;
import org.eclipse.che.workspace.infrastructure.kubernetes.StartSynchronizerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.KubernetesNamespaceService;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.AuthorizationChecker;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.PermissionsCleaner;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.jpa.JpaKubernetesRuntimeCacheModule;
import org.eclipse.che.workspace.infrastructure.kubernetes.devfile.DockerimageComponentToWorkspaceApplier;
import org.eclipse.che.workspace.infrastructure.kubernetes.devfile.KubernetesComponentToWorkspaceApplier;
@ -80,6 +82,7 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.PluginBroke
import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.SidecarToolingProvisioner;
import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.brokerphases.BrokerEnvironmentFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.events.BrokerService;
import org.eclipse.che.workspace.infrastructure.openshift.authorization.OpenShiftAuthorizationCheckerImpl;
import org.eclipse.che.workspace.infrastructure.openshift.devfile.OpenshiftComponentToWorkspaceApplier;
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentFactory;
@ -118,6 +121,9 @@ public class OpenShiftInfraModule extends AbstractModule {
namespaceConfigurators.addBinding().to(SshKeysConfigurator.class);
namespaceConfigurators.addBinding().to(GitconfigUserDataConfigurator.class);
bind(AuthorizationChecker.class).to(OpenShiftAuthorizationCheckerImpl.class);
bind(PermissionsCleaner.class).asEagerSingleton();
bind(KubernetesNamespaceService.class);
MapBinder<String, InternalEnvironmentFactory> factories =

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2012-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
*/
package org.eclipse.che.workspace.infrastructure.openshift.authorization;
import static org.eclipse.che.commons.lang.StringUtils.strToSet;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.openshift.api.model.Group;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.AuthorizationChecker;
/** This {@link OpenShiftAuthorizationCheckerImpl} checks if user is allowed to use Che. */
@Singleton
public class OpenShiftAuthorizationCheckerImpl implements AuthorizationChecker {
private final CheServerKubernetesClientFactory cheServerKubernetesClientFactory;
private final Set<String> allowUsers;
private final Set<String> allowGroups;
private final Set<String> denyUsers;
private final Set<String> denyGroups;
@Inject
public OpenShiftAuthorizationCheckerImpl(
@Nullable @Named("che.infra.kubernetes.advanced_authorization.allow_users") String allowUsers,
@Nullable @Named("che.infra.kubernetes.advanced_authorization.allow_groups")
String allowGroups,
@Nullable @Named("che.infra.kubernetes.advanced_authorization.deny_users") String denyUsers,
@Nullable @Named("che.infra.kubernetes.advanced_authorization.deny_groups") String denyGroups,
CheServerKubernetesClientFactory cheServerKubernetesClientFactory) {
this.allowUsers = strToSet(allowUsers);
this.allowGroups = strToSet(allowGroups);
this.denyUsers = strToSet(denyUsers);
this.denyGroups = strToSet(denyGroups);
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
}
public boolean isAuthorized(String username) throws InfrastructureException {
return isAllowedUser(cheServerKubernetesClientFactory.create(), username)
&& !isDeniedUser(cheServerKubernetesClientFactory.create(), username);
}
private boolean isAllowedUser(KubernetesClient client, String username) {
// All users from all groups are allowed by default
if (allowUsers.isEmpty() && allowGroups.isEmpty()) {
return true;
}
if (allowUsers.contains(username)) {
return true;
}
for (String groupName : allowGroups) {
Group group = client.resources(Group.class).withName(groupName).get();
if (group != null && group.getUsers().contains(username)) {
return true;
}
}
return false;
}
private boolean isDeniedUser(KubernetesClient client, String username) {
// All users from all groups are allowed by default
if (denyUsers.isEmpty() && denyGroups.isEmpty()) {
return false;
}
if (denyUsers.contains(username)) {
return true;
}
for (String groupName : denyGroups) {
Group group = client.resources(Group.class).withName(groupName).get();
if (group != null && group.getUsers().contains(username)) {
return true;
}
}
return false;
}
}

View File

@ -40,6 +40,8 @@ import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.server.impls.KubernetesNamespaceMetaImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.AuthorizationChecker;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.PermissionsCleaner;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.NamespaceConfigurator;
import org.eclipse.che.workspace.infrastructure.kubernetes.util.KubernetesSharedPool;
@ -81,6 +83,8 @@ public class OpenShiftProjectFactory extends KubernetesNamespaceFactory {
CheServerOpenshiftClientFactory cheServerOpenshiftClientFactory,
PreferenceManager preferenceManager,
KubernetesSharedPool sharedPool,
AuthorizationChecker authorizationChecker,
PermissionsCleaner permissionsCleaner,
@Nullable @Named("che.infra.openshift.oauth_identity_provider")
String oAuthIdentityProvider) {
super(
@ -93,7 +97,9 @@ public class OpenShiftProjectFactory extends KubernetesNamespaceFactory {
namespaceConfigurators,
cheServerKubernetesClientFactory,
preferenceManager,
sharedPool);
sharedPool,
authorizationChecker,
permissionsCleaner);
this.initWithCheServerSa = initWithCheServerSa;
this.cheServerKubernetesClientFactory = cheServerKubernetesClientFactory;
this.cheServerOpenshiftClientFactory = cheServerOpenshiftClientFactory;
@ -105,6 +111,9 @@ public class OpenShiftProjectFactory extends KubernetesNamespaceFactory {
OpenShiftProject osProject = get(identity);
var subject = EnvironmentContext.getCurrent().getSubject();
var userName = subject.getUserName();
validateAuthorization(osProject.getName(), userName);
NamespaceResolutionContext resolutionCtx =
new NamespaceResolutionContext(identity.getWorkspaceId(), subject.getUserId(), userName);
Map<String, String> namespaceAnnotationsEvaluated =

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2012-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
*/
package org.eclipse.che.workspace.infrastructure.openshift.authorization;
import static org.mockito.Mockito.*;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
import io.fabric8.openshift.api.model.Group;
import java.util.Collections;
import java.util.List;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
@Listeners(MockitoTestNGListener.class)
public class OpenShiftAuthorizationCheckerTest {
@Mock private CheServerKubernetesClientFactory clientFactory;
private KubernetesClient client;
private KubernetesServer serverMock;
@BeforeMethod
public void setUp() throws InfrastructureException {
serverMock = new KubernetesServer(true, true);
serverMock.before();
client = spy(serverMock.getClient());
lenient().when(clientFactory.create()).thenReturn(client);
}
@Test(dataProvider = "advancedAuthorizationData")
public void advancedAuthorization(
String testUserName,
List<Group> groups,
String allowedUsers,
String allowedGroups,
String deniedUsers,
String deniedGroups,
boolean expectedIsAuthorized)
throws InfrastructureException {
// give
OpenShiftAuthorizationCheckerImpl authorizationChecker =
new OpenShiftAuthorizationCheckerImpl(
allowedUsers, allowedGroups, deniedUsers, deniedGroups, clientFactory);
groups.forEach(group -> client.resources(Group.class).create(group));
// when
boolean isAuthorized = authorizationChecker.isAuthorized(testUserName);
// then
Assert.assertEquals(isAuthorized, expectedIsAuthorized);
}
@DataProvider
public static Object[][] advancedAuthorizationData() {
Group groupWithUser1 =
new Group(
"v1",
"Group",
new ObjectMetaBuilder().withName("groupWithUser1").build(),
List.of("user1"));
Group groupWithUser2 =
new Group(
"v1",
"Group",
new ObjectMetaBuilder().withName("groupWithUser2").build(),
List.of("user2"));
return new Object[][] {
{"user1", Collections.emptyList(), "", "", "", "", true},
{"user1", Collections.emptyList(), "user1", "", "", "", true},
{"user1", Collections.emptyList(), "user1", "", "user2", "", true},
{"user1", List.of(groupWithUser2), "user1", "", "", "groupWithUser2", true},
{"user1", List.of(groupWithUser1), "", "groupWithUser1", "", "", true},
{"user2", List.of(groupWithUser1), "user2", "groupWithUser1", "", "", true},
{
"user1",
List.of(groupWithUser1, groupWithUser2),
"",
"groupWithUser1",
"",
"groupWithUser2",
true
},
{"user1", Collections.emptyList(), "user1", "", "user1", "", false},
{"user2", Collections.emptyList(), "user1", "", "", "", false},
{"user2", Collections.emptyList(), "user1", "", "user2", "", false},
{"user2", List.of(groupWithUser1), "", "groupWithUser1", "", "", false},
{"user1", Collections.emptyList(), "", "", "user1", "", false},
{"user1", List.of(groupWithUser1), "", "", "", "groupWithUser1", false},
{"user1", List.of(groupWithUser1), "", "groupWithUser1", "", "groupWithUser1", false},
{
"user2",
List.of(groupWithUser1, groupWithUser2),
"",
"groupWithUser1",
"",
"groupWithUser2",
false
},
};
}
}

View File

@ -71,6 +71,8 @@ import org.eclipse.che.commons.subject.SubjectImpl;
import org.eclipse.che.inject.ConfigurationException;
import org.eclipse.che.workspace.infrastructure.kubernetes.CheServerKubernetesClientFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.AuthorizationChecker;
import org.eclipse.che.workspace.infrastructure.kubernetes.authorization.PermissionsCleaner;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesConfigsMaps;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesSecrets;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.NamespaceConfigurator;
@ -113,6 +115,8 @@ public class OpenShiftProjectFactoryTest {
@Mock private WorkspaceManager workspaceManager;
@Mock private PreferenceManager preferenceManager;
@Mock private KubernetesSharedPool pool;
@Mock private AuthorizationChecker authorizationChecker;
@Mock private PermissionsCleaner permissionsCleaner;
@Mock private ProjectOperation projectOperation;
@ -134,6 +138,7 @@ public class OpenShiftProjectFactoryTest {
lenient().when(cheServerOpenshiftClientFactory.createOC()).thenReturn(osClient);
lenient().when(cheServerKubernetesClientFactory.create()).thenReturn(osClient);
lenient().when(osClient.projects()).thenReturn(projectOperation);
lenient().when(authorizationChecker.isAuthorized(anyString())).thenReturn(true);
lenient()
.when(workspaceManager.getWorkspace(any()))
@ -174,6 +179,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
projectFactory.checkIfNamespaceIsAllowed(USER_NAME + "-che");
@ -204,6 +211,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
try {
projectFactory.checkIfNamespaceIsAllowed("any-namespace");
@ -234,6 +243,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
}
@ -269,6 +280,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));
@ -305,6 +318,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "u123", null, false));
@ -337,6 +352,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
// when
@ -379,6 +396,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
List<KubernetesNamespaceMeta> availableNamespaces = projectFactory.list();
@ -415,6 +434,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
List<KubernetesNamespaceMeta> availableNamespaces = projectFactory.list();
@ -451,6 +472,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
projectFactory.list();
@ -477,6 +500,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
projectFactory.list();
@ -508,6 +533,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER));
OpenShiftProject toReturnProject = mock(OpenShiftProject.class);
prepareProject(toReturnProject);
@ -542,6 +569,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER));
OpenShiftProject toReturnProject = mock(OpenShiftProject.class);
doReturn(toReturnProject).when(projectFactory).doCreateProjectAccess(any(), any());
@ -584,6 +613,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER));
OpenShiftProject toReturnProject = mock(OpenShiftProject.class);
prepareProject(toReturnProject);
@ -628,6 +659,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
OAUTH_IDENTITY_PROVIDER));
OpenShiftProject toReturnProject = mock(OpenShiftProject.class);
when(toReturnProject.getName()).thenReturn("workspace123");
@ -677,6 +710,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
String namespace =
@ -709,6 +744,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER);
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));
projectFactory.list();
@ -735,6 +772,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER));
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));
OpenShiftProject toReturnProject = mock(OpenShiftProject.class);
@ -775,6 +814,8 @@ public class OpenShiftProjectFactoryTest {
cheServerOpenshiftClientFactory,
preferenceManager,
pool,
authorizationChecker,
permissionsCleaner,
NO_OAUTH_IDENTITY_PROVIDER));
EnvironmentContext.getCurrent().setSubject(new SubjectImpl("jondoe", "123", null, false));

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-server</artifactId>
<groupId>org.eclipse.che</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.che.infrastructure</groupId>

View File

@ -37,23 +37,6 @@ loadMvnSettingsGpgKey() {
gpg --version
}
# comment out: why do we think we need nodejs installed for a java build?
# installDebDeps(){
# set +x
# curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
# sudo apt-get install -y nodejs
# }
# comment out: already installed via GH action so no need to do it again
# installMaven(){
# set -x
# mkdir -p /opt/apache-maven && curl -sSL https://downloads.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz | tar -xz --strip=1 -C /opt/apache-maven
# export M2_HOME="/opt/apache-maven"
# export PATH="/opt/apache-maven/bin:${PATH}"
# mvn -version || die_with "mvn not found in path: ${PATH} !"
# set +x
# }
evaluateCheVariables() {
echo "Che version: ${CHE_VERSION}"
# derive branch from version
@ -280,6 +263,7 @@ releaseTypescriptDto() {
}
buildImages() {
export BUILDER="docker"
echo "Going to build docker images"
set -e
set -o pipefail
@ -392,14 +376,8 @@ updateImageTagsInCheServer() {
popd >/dev/null
}
# already installed via GH action so no need to do it again
# installMaven
loadMvnSettingsGpgKey
# why do we think we need nodejs installed for a java build?
# installDebDeps
set -x
setupGitconfig

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-authentication-commons</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-authorization-impl</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-authorization</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-organization-shared</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-organization</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-permission-shared</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-permission</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-resource-shared</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-resource</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-api</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-api-workspace-activity</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-parent</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>che-multiuser-api</artifactId>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-integration-tests</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-cascade-removal</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-integration-tests</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-mysql-tck</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-integration-tests</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-postgresql-tck</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-parent</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-integration-tests</artifactId>
<packaging>pom</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-keycloak</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-keycloak-server</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-keycloak</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-keycloak-shared</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-keycloak</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-keycloak-token-provider</artifactId>
<name>Che Multiuser :: Keycloak Token Provider</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-keycloak</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-keycloak-user-remover</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-parent</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>che-multiuser-keycloak</artifactId>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-machine-auth</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-machine-authentication-shared</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-machine-auth</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-machine-authentication</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-parent</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>che-multiuser-machine-auth</artifactId>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-parent</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-oidc</artifactId>
<packaging>jar</packaging>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-permission</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-permission-devfile</artifactId>
<name>Che Multiuser :: Devfile Permissions</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-permission</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-permission-logger</artifactId>
<name>Che Multiuser :: Logger Permissions</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-permission</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-permission-resource</artifactId>
<name>Che Multiuser :: Resource :: Permissions</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-permission</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-permission-system</artifactId>
<name>Che Multiuser :: System Permissions</name>

View File

@ -17,7 +17,7 @@
<parent>
<artifactId>che-multiuser-permission</artifactId>
<groupId>org.eclipse.che.multiuser</groupId>
<version>7.78.0-SNAPSHOT</version>
<version>7.80.0-SNAPSHOT</version>
</parent>
<artifactId>che-multiuser-permission-user</artifactId>
<name>Che Multiuser :: User Permissions</name>

Some files were not shown because too many files have changed in this diff Show More