From eb550c5a382501c61b46ecf08f2c4383f5d1afc2 Mon Sep 17 00:00:00 2001 From: Atharva Rane <41084525+atharvar28@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:05:12 -0400 Subject: [PATCH] Migrate OIDC client Tests (#107) * Migrate OIDC client Tests * update tests to get client_creds * fix client_creds test * update conftest.py marker code * fix centralized_auth tests * Update shared_integration_tests.yaml * changes for OIDC * Update shared_integration_tests.yaml * Changes for jenkins-client-tester * Changes for removing client info files * Update gen3_admin_tasks.py --------- Co-authored-by: Krishna Agarwal <159047652+krishnaa05@users.noreply.github.com> Co-authored-by: Krishna Agarwal --- .../workflows/shared_integration_tests.yaml | 2 +- .secrets.baseline | 170 +++++++++++++++-- gen3-integration-tests/conftest.py | 8 + .../ci-only-audit-service-logging.groovy | 4 +- .../ci-only-check-kube-job-pod.groovy | 14 +- .../ci-only-check_indices_after_etl.groovy | 4 +- .../ci-only-clean-up-indices.groovy | 4 +- .../ci-only-create-access-token.groovy | 2 +- ...nly-create-link-google-test-buckets.groovy | 8 +- .../ci-only-fence-client-rotate.groovy | 72 +++++++ .../ci-only-fence-create-client.groovy | 31 ++- .../ci-only-fence-delete-client.groovy | 11 +- ...nce-disable-register-users-redirect.groovy | 2 +- ...ence-enable-register-users-redirect.groovy | 4 +- .../ci-only-fence-force-link-google.groovy | 2 +- .../jenkins_jobs/ci-only-fetch-configs.groovy | 2 +- .../ci-only-generate-api-key.groovy | 4 +- .../ci-only-kube-setup-service.groovy | 2 +- .../ci-only-modify-env-for-service-pr.groovy | 2 +- ...ci-only-modify-env-for-test-repo-pr.groovy | 2 +- .../ci-only-revoke-arborist-policy.groovy | 2 +- .../ci-only-run-gen3-command.groovy | 4 +- .../jenkins_jobs/ci-only-run-gen3-job.groovy | 6 +- .../jenkins_jobs/ci-only-save-pod-logs.groovy | 4 +- .../ci-only-select-and-lock-namespace.groovy | 4 +- .../ci-only-unlock-namespace.groovy | 2 +- gen3-integration-tests/pages/login.py | 2 - gen3-integration-tests/pyproject.toml | 2 +- gen3-integration-tests/services/fence.py | 26 --- .../tests/test_centralized_auth.py | 20 +- .../tests/test_client_credentials.py | 5 +- gen3-integration-tests/tests/test_oauth2.py | 23 +-- .../tests/test_oidc_client.py | 177 ++++++++++++++++++ .../utils/gen3_admin_tasks.py | 26 ++- gen3-integration-tests/utils/test_setup.py | 50 +++++ 35 files changed, 578 insertions(+), 125 deletions(-) create mode 100644 gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-client-rotate.groovy create mode 100644 gen3-integration-tests/tests/test_oidc_client.py diff --git a/.github/workflows/shared_integration_tests.yaml b/.github/workflows/shared_integration_tests.yaml index 51e802af..b1e49972 100644 --- a/.github/workflows/shared_integration_tests.yaml +++ b/.github/workflows/shared_integration_tests.yaml @@ -187,7 +187,7 @@ jobs: continue-on-error: true # if this fails, we still need to run clean-up steps run: | mkdir output - poetry run pytest -n auto -m "not wip and ${{ inputs.SERVICE_TO_TEST }}" --alluredir allure-results --no-header --dist loadscope ${{ env.TEST_LABEL }} + poetry run pytest -n auto -m "${{ inputs.SERVICE_TO_TEST }} and not wip" --alluredir allure-results --no-header --dist loadscope ${{ env.TEST_LABEL }} - name: Run tests id: run_tests diff --git a/.secrets.baseline b/.secrets.baseline index 1599d5c0..db2a0d0f 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -112,6 +112,143 @@ } ], "results": { + "gen3-integration-tests/test_data/fence_clients/client_rotate_creds.txt": [ + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/client_rotate_creds.txt", + "hashed_secret": "53709eebcf139fb2ca486c04f065070e321c102a", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/client_rotate_creds.txt", + "hashed_secret": "fd145b883f4f94e6baad59399cc542f7ac49a5d8", + "is_verified": false, + "line_number": 1 + } + ], + "gen3-integration-tests/test_data/fence_clients/clients_creds.txt": [ + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "17b898c11407d972798982c364c70dd03bd0fb62", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "ab3e0294932fe7abad9fb58c3e41758b90e70595", + "is_verified": false, + "line_number": 1 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "ff0f231c5344e69d56e1e554b623949911279ca6", + "is_verified": false, + "line_number": 2 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "01662b9143b84b0eaae23336237cde7bf39ab042", + "is_verified": false, + "line_number": 3 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "f1cce78768a849beac11d93ec43ba565e819c0da", + "is_verified": false, + "line_number": 3 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "95c46bac73679ff696a2843f65df7964cdce78ab", + "is_verified": false, + "line_number": 4 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "a73f004e3889b1342751d4670b09dc15cfc51327", + "is_verified": false, + "line_number": 4 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "6014178b480b477133815cca5276dc03361d9310", + "is_verified": false, + "line_number": 5 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "7c9aa25179da69db33502af670476fc20182093c", + "is_verified": false, + "line_number": 5 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "c4cd1dd1f8cd6186c0ed46bc29a784c7ec26b2c9", + "is_verified": false, + "line_number": 6 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "d8edfaea81724f5a10855691d92f61de66280269", + "is_verified": false, + "line_number": 6 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "9ed12c9978fcc9cebc65cd1fc5ef366de62c9734", + "is_verified": false, + "line_number": 7 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "e37ec01ad0109eec802dfbd617e162080c835316", + "is_verified": false, + "line_number": 7 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "3c4d365b05bba7dca96ef316a7596fa01b108abf", + "is_verified": false, + "line_number": 8 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "9212e6bd53da0a2bcb0a41119ee2378d9b0d3e2c", + "is_verified": false, + "line_number": 8 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "089f848c95240e6ec6b14a4da935253a00555a99", + "is_verified": false, + "line_number": 9 + }, + { + "type": "Base64 High Entropy String", + "filename": "gen3-integration-tests/test_data/fence_clients/clients_creds.txt", + "hashed_secret": "57be9b25b765c9c7b16c05481e1d05885eff83a8", + "is_verified": false, + "line_number": 9 + } + ], "gen3-integration-tests/test_data/study_registration/study.json": [ { "type": "Hex High Entropy String", @@ -154,7 +291,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "62bd0c4d3a6b445b13212d23500a7f0916757c3e", "is_verified": false, - "line_number": 30, + "line_number": 29, "is_secret": false }, { @@ -162,7 +299,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "e1fa8c0685ac2b51db97b7bd00b9afa63489d30c", "is_verified": false, - "line_number": 37, + "line_number": 36, "is_secret": false }, { @@ -170,7 +307,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "faad2c1400e2071d0b52a70589e6a69e960a8f66", "is_verified": false, - "line_number": 44, + "line_number": 43, "is_secret": false }, { @@ -178,7 +315,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "e9728a38017dc43b9240cc2a554bbc85c4951ac9", "is_verified": false, - "line_number": 54, + "line_number": 53, "is_secret": false }, { @@ -186,7 +323,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "c9db8b43a10ab86e1ff61c6639f7d12ec42538ba", "is_verified": false, - "line_number": 64, + "line_number": 63, "is_secret": false }, { @@ -194,7 +331,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "784c6e9de4ecdc99633fd8df4bb46d1a547cce47", "is_verified": false, - "line_number": 74, + "line_number": 73, "is_secret": false }, { @@ -202,7 +339,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "e0023bf0f573f727496fa24af0c1d26f05b23fc8", "is_verified": false, - "line_number": 84, + "line_number": 83, "is_secret": false }, { @@ -210,7 +347,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "191e56b8fb18e2008781d6953cbb73be28ce66e7", "is_verified": false, - "line_number": 96, + "line_number": 95, "is_secret": false }, { @@ -218,7 +355,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "7c3be26a466754059b7c75e8b459a4ade9c2117f", "is_verified": false, - "line_number": 103, + "line_number": 102, "is_secret": false }, { @@ -226,7 +363,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "e19559ed661532682397daed1651e91321c4c8c4", "is_verified": false, - "line_number": 113, + "line_number": 112, "is_secret": false }, { @@ -234,7 +371,7 @@ "filename": "gen3-integration-tests/tests/test_centralized_auth.py", "hashed_secret": "9ec16d1f5ec2441b412f6ddef0676376a6bf7dd4", "is_verified": false, - "line_number": 120, + "line_number": 119, "is_secret": false } ], @@ -308,6 +445,15 @@ "is_secret": false } ], + "gen3-integration-tests/tests/test_oidc_client.py": [ + { + "type": "Hex High Entropy String", + "filename": "gen3-integration-tests/tests/test_oidc_client.py", + "hashed_secret": "62bd0c4d3a6b445b13212d23500a7f0916757c3e", + "is_verified": false, + "line_number": 145 + } + ], "gen3-integration-tests/tests/test_presigned_url.py": [ { "type": "Hex High Entropy String", @@ -338,5 +484,5 @@ } ] }, - "generated_at": "2024-08-29T17:35:31Z" + "generated_at": "2024-09-05T21:36:22Z" } diff --git a/gen3-integration-tests/conftest.py b/gen3-integration-tests/conftest.py index 821b0d00..10d8d46e 100644 --- a/gen3-integration-tests/conftest.py +++ b/gen3-integration-tests/conftest.py @@ -59,10 +59,17 @@ def pytest_collection_finish(session): for marker_name, marker in markers.items(): if marker_name == "requires_fence_client": setup.get_fence_client_info() + setup.get_fence_rotated_client_info() requires_fence_client_marker_present = True return +@pytest.fixture(scope="session", autouse=True) +def get_fence_clients(): + setup.get_client_id_secret() + setup.get_rotated_client_id_secret() + + def pytest_configure(config): # Compute hostname and namespace hostname = os.getenv("HOSTNAME") @@ -83,6 +90,7 @@ def pytest_configure(config): # Clients used for testing pytest.clients = {} + pytest.rotated_clients = {} # Accounts used for testing pytest.users = {} pytest.users["main_account"] = "cdis.autotest@gmail.com" # default user diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-audit-service-logging.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-audit-service-logging.groovy index fb26c33f..8640c83e 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-audit-service-logging.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-audit-service-logging.groovy @@ -38,7 +38,7 @@ pipeline { timeout(time: 5, unit: 'MINUTES') // timeout on this stage } steps { - dir("audit-service-logging"){ + dir("ci-only-audit-service-logging"){ script { try { sh '''#!/bin/bash +x @@ -54,7 +54,7 @@ pipeline { shopt -s xpg_echo; echo "ENABLE_AUDIT_LOGS:\n presigned_url: \${AUDIT_LOGGING}\n login: \${AUDIT_LOGGING}" >> fence_config_tmp.yaml # Update the Secret - g3kubectl get secret fence-config -o json | jq --arg new_config "$(cat fence_config_tmp.yaml | base64)" '.data["fence-config.yaml"]=$new_config' | g3kubectl apply -f - + kubectl get secret fence-config -o json | jq --arg new_config "$(cat fence_config_tmp.yaml | base64)" '.data["fence-config.yaml"]=$new_config' | kubectl apply -f - # Roll the fence and presigned-url-fence pods gen3 roll fence; gen3 roll presigned-url-fence diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-check-kube-job-pod.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-check-kube-job-pod.groovy index 7c253552..81c25156 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-check-kube-job-pod.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-check-kube-job-pod.groovy @@ -40,7 +40,7 @@ pipeline { timeout(time: 5, unit: 'MINUTES') // timeout on this stage } steps { - dir("check-kube-pod"){ + dir("ci-only-check-kube-pod"){ script { try { sh '''#!/bin/bash +x @@ -55,24 +55,27 @@ pipeline { echo "Waiting for $JOB_NAME job pod ..." # checking if there are pods with LABEL_NAME mentioned in parameters - POD_NAMES=$(g3kubectl -n $KUBECTL_NAMESPACE get pod --sort-by=.metadata.creationTimestamp -l app=$LABEL_NAME -o json | jq -r '.items[] | select(.metadata.name | test("^'"$JOB_NAME"'")) | .metadata.name') + POD_NAMES=$(kubectl -n $KUBECTL_NAMESPACE get pod --sort-by=.metadata.creationTimestamp -l app=$LABEL_NAME -o json | jq -r '.items[] | select(.metadata.name | test("^'"$JOB_NAME"'")) | .metadata.name') if [[ -z "$POD_NAMES" ]]; then echo "No pods found with label $LABEL_NAME" else # if pod/s found, get the status of the latest pod LATEST_POD=$(echo "$POD_NAMES" | tail -n 1) echo "Pod found with label $LABEL_NAME: $LATEST_POD" - POD_STATUS=$(g3kubectl -n $KUBECTL_NAMESPACE get pod $LATEST_POD -o jsonpath='{.status.phase}') + POD_STATUS=$(kubectl -n $KUBECTL_NAMESPACE get pod $LATEST_POD -o jsonpath='{.status.phase}') echo "Pod status: $POD_STATUS" if [ "$POD_STATUS" == "Succeeded" ]; then echo "The container from pod $LATEST_POD is ready! Proceed with the assertion checks..." + kubectl logs $LATEST_POD -n $NAMESPACE > logs.txt break elif [ "$POD_STATUS" == "Failed" ]; then if [ "$EXPECT_FAILURE" == "True" ]; then echo "The container from pod $LATEST_POD failed as expected! Just ignore as this is part of a negative test." + kubectl logs $LATEST_POD -n $NAMESPACE > logs.txt break else echo "THE POD FAILED. GIVING UP." + kubectl logs $LATEST_POD -n $NAMESPACE > logs.txt POD_LOGS=$(kubectl logs $LATEST_POD -n $NAMESPACE) echo "Logs:\n$POD_LOGS" exit 1 @@ -91,4 +94,9 @@ pipeline { } } } + post { + always { + archiveArtifacts artifacts: 'check-kube-pod/logs.txt' + } + } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-check_indices_after_etl.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-check_indices_after_etl.groovy index 2b7fb71f..8c5203fe 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-check_indices_after_etl.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-check_indices_after_etl.groovy @@ -29,14 +29,14 @@ pipeline { } stage('Check Indices After ETL') { steps { - dir("check-indices-after-etl"){ + dir("ci-only-check-indices-after-etl"){ sh '''#!/bin/bash +x set -e export GEN3_HOME=\$WORKSPACE/cloud-automation export KUBECTL_NAMESPACE=\${NAMESPACE} source $GEN3_HOME/gen3/gen3setup.sh - etlMappingNames=$(g3kubectl get cm etl-mapping -o jsonpath='{.data.etlMapping\\.yaml}' | yq '.mappings[].name' | xargs) + etlMappingNames=$(kubectl get cm etl-mapping -o jsonpath='{.data.etlMapping\\.yaml}' | yq '.mappings[].name' | xargs) IFS=' ' read -r -a aliases <<< "$etlMappingNames" echo "${aliases[@]}" diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-clean-up-indices.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-clean-up-indices.groovy index e21e6297..cb89c9f2 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-clean-up-indices.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-clean-up-indices.groovy @@ -29,7 +29,7 @@ pipeline { } stage('Clean Up Indices') { steps { - dir("clean-up-indices"){ + dir("ci-only-clean-up-indices"){ sh '''#!/bin/bash +x set -e export GEN3_HOME=\$WORKSPACE/cloud-automation @@ -37,7 +37,7 @@ pipeline { source $GEN3_HOME/gen3/gen3setup.sh # get etlmapping names - etlMappingNames=$(g3kubectl get cm etl-mapping -o jsonpath='{.data.etlMapping\\.yaml}' | yq '.mappings[].name' | xargs) + etlMappingNames=$(kubectl get cm etl-mapping -o jsonpath='{.data.etlMapping\\.yaml}' | yq '.mappings[].name' | xargs) IFS=' ' read -r -a indices <<< "$etlMappingNames" # Add the "-array-config" suffix to each element diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-create-access-token.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-create-access-token.groovy index 7feaad47..cdd55f83 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-create-access-token.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-create-access-token.groovy @@ -52,7 +52,7 @@ pipeline { source $GEN3_HOME/gen3/gen3setup.sh # Create access token - g3kubectl exec $(gen3 pod \$SERVICE \$NAMESPACE) -- fence-create token-create --scopes openid,user,fence,data,credentials,google_service_account,google_credentials --type access_token --exp \$EXPIRATION --username \$USERNAME > access_token.txt + kubectl exec $(gen3 pod \$SERVICE \$NAMESPACE) -- fence-create token-create --scopes openid,user,fence,data,credentials,google_service_account,google_credentials --type access_token --exp \$EXPIRATION --username \$USERNAME > access_token.txt ''' } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-create-link-google-test-buckets.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-create-link-google-test-buckets.groovy index 50f5138a..e7a6af7d 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-create-link-google-test-buckets.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-create-link-google-test-buckets.groovy @@ -110,12 +110,12 @@ spec: source $GEN3_HOME/gen3/gen3setup.sh # Create Google Test Buckets - g3kubectl exec $(gen3 pod fence \${NAMESPACE}) -- fence-create google-bucket-create --unique-name dcf-integration-qa --google-project-id dcf-integration --project-auth-id QA --public False - g3kubectl exec $(gen3 pod fence \${NAMESPACE}) -- fence-create google-bucket-create --unique-name dcf-integration-test --google-project-id dcf-integration --project-auth-id test --public False + kubectl exec $(gen3 pod fence \${NAMESPACE}) -- fence-create google-bucket-create --unique-name dcf-integration-qa --google-project-id dcf-integration --project-auth-id QA --public False + kubectl exec $(gen3 pod fence \${NAMESPACE}) -- fence-create google-bucket-create --unique-name dcf-integration-test --google-project-id dcf-integration --project-auth-id test --public False # Link phs ids to existing buckets - g3kubectl exec $(gen3 pod fence \${NAMESPACE}) -- fence-create link-bucket-to-project --project_auth_id phs000179 --bucket_id dcf-integration-qa --bucket_provider google - g3kubectl exec $(gen3 pod fence \${NAMESPACE}) -- fence-create link-bucket-to-project --project_auth_id phs000178 --bucket_id dcf-integration-test --bucket_provider google + kubectl exec $(gen3 pod fence \${NAMESPACE}) -- fence-create link-bucket-to-project --project_auth_id phs000179 --bucket_id dcf-integration-qa --bucket_provider google + kubectl exec $(gen3 pod fence \${NAMESPACE}) -- fence-create link-bucket-to-project --project_auth_id phs000178 --bucket_id dcf-integration-test --bucket_provider google ''' } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-client-rotate.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-client-rotate.groovy new file mode 100644 index 00000000..261a6e7c --- /dev/null +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-client-rotate.groovy @@ -0,0 +1,72 @@ +/* + String parameter NAMESPACE + e.g. jenkins-blood +*/ +pipeline { + agent { + node { + label 'gen3-ci-worker' + } + } + stages { + stage('Clean old workspace') { + steps { + cleanWs() + } + } + stage('Initial Setup') { + steps { + // cloud-automation + checkout([ + $class: 'GitSCM', + branches: [[name: 'refs/heads/master']], + doGenerateSubmoduleConfigurations: false, + extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'cloud-automation']], + submoduleCfg: [], + userRemoteConfigs: [[credentialsId: 'PlanXCyborgUserJenkins', url: 'https://github.com/uc-cdis/cloud-automation.git']] + ]) + } + } + stage('Fence Client Rotation') { + steps { + dir("ci-only-fence-client-rotate"){ + script { + sh '''#!/bin/bash +x + set -e + export GEN3_HOME=\$WORKSPACE/cloud-automation + export KUBECTL_NAMESPACE=\${NAMESPACE} + source $GEN3_HOME/gen3/gen3setup.sh + # CLIENT_NAME,EXPIRES_IN + client_details=( + "jenkins-client-tester," + ) + + for value in "${client_details[@]}"; do + # Split the variable into an array using comma as the delimiter + IFS=',' read -r CLIENT_NAME EXPIRES_IN <<< "${value}" + # construct fence-create command depending on the parameters provided by the run + FENCE_CMD="kubectl -n $KUBECTL_NAMESPACE exec $(gen3 pod fence) -- fence-create client-rotate --client ${CLIENT_NAME}" + echo "${FENCE_CMD}" + if [[ -n $EXPIRES_IN ]]; then + FENCE_CMD="${FENCE_CMD} --expires-in ${EXPIRES_IN}" + fi + echo "Running: ${FENCE_CMD}" + # execute the above fence command + FENCE_CMD_RES=$(bash -c "${FENCE_CMD}" | tee >(awk -v prefix="$CLIENT_NAME" 'END{print prefix ":" $0}' >> client_rotate_creds.txt)) + done + + # Run usersync + gen3 job run usersync ADD_DBGAP true + kubectl wait --for=condition=complete --timeout=-1s jobs/usersync + ''' + } + } + } + } + } + post { + always { + archiveArtifacts artifacts: 'ci-only-fence-client-rotate/client_rotate_creds.txt' + } + } +} diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-create-client.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-create-client.groovy index 61f3a370..332e513a 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-create-client.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-create-client.groovy @@ -2,7 +2,7 @@ String parameter NAMESPACE e.g. jenkins-blood - Artifact archived - + Artifact archived - clients_creds.txt */ pipeline { agent { @@ -31,7 +31,7 @@ pipeline { } stage('Create Fence Client') { steps { - dir("create-fence-client"){ + dir("ci-only-create-fence-client"){ script { sh '''#!/bin/bash +x set -e @@ -45,11 +45,11 @@ pipeline { "basic-test-client,test-client@example.com,basic,None," "implicit-test-client,test@example.com,implicit,None," "basic-test-abc-client,test-abc-client@example.com,basic,None," - "jenkinsClientTester,dcf-integration-test-0@planx-pla.net,client_credentials,None," - "jenkinsClientNoExpiration,test-user,client_credentials,None," - "jenkinsClientShortExpiration,test-user,client_credentials,None,0.00000000001" - "jenkinsClientMediumExpiration,test-user,client_credentials,None,4" - "jenkinsClientLongExpiration,test-user,client_credentials,None,30" + "jenkins-client-tester,dcf-integration-test-0@planx-pla.net,client_credentials,None," + "jenkins-client-no-expiration,test-user,client_credentials,None," + "jenkins-client-short-expiration,test-user,client_credentials,None,0.00000000001" + "jenkins-client-medium-expiration,test-user,client_credentials,None,4" + "jenkins-client-long-expiration,test-user,client_credentials,None,30" "ras-test-client,UCtestuser128,basic,programs.QA-admin programs.test-admin programs.DEV-admin programs.jnkns-admin," ) @@ -90,22 +90,13 @@ pipeline { echo "Running: ${FENCE_CMD}" # execute the above fence command - FENCE_CMD_RES=$(bash -c "${FENCE_CMD}" | tee >(tail -n 1 > temp_client_cred.txt)) - file_content=$(cat temp_client_cred.txt) - - case "$CLIENT_TYPE" in - "implicit") - CLIENT_CREDS=$(echo "$file_content" | sed -e "s/(\\('\\(.*\\)'\\),None)/\\2,None/" -e "s/(\\('\\(.*\\)'\\), \\(.*\\))/$CLIENT_NAME: \\2,\\3/") - ;; - *) - CLIENT_CREDS=$(echo "$file_content" | sed -e "s/(\\('\\(.*\\)'\\), '\\(.*\\)')/$CLIENT_NAME: \\2,\\3/") - esac - echo $CLIENT_CREDS >> clients_creds.txt + # execute the above fence command + FENCE_CMD_RES=$(bash -c "${FENCE_CMD}" | tee >(awk -v prefix="$CLIENT_NAME" 'END{print prefix ":" $0}' >> clients_creds.txt)) done # Run usersync gen3 job run usersync ADD_DBGAP true - g3kubectl wait --for=condition=complete --timeout=-1s jobs/usersync + kubectl wait --for=condition=complete --timeout=-1s jobs/usersync ''' } } @@ -114,7 +105,7 @@ pipeline { } post { always { - archiveArtifacts artifacts: 'create-fence-client/clients_creds.txt' + archiveArtifacts artifacts: 'ci-only-create-fence-client/clients_creds.txt' } } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-delete-client.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-delete-client.groovy index 5e1a9a27..e21af5d6 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-delete-client.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-delete-client.groovy @@ -43,11 +43,12 @@ pipeline { "basic-test-client" "implicit-test-client" "basic-test-abc-client" - "jenkinsClientTester" - "jenkinsClientNoExpiration" - "jenkinsClientShortExpiration" - "jenkinsClientMediumExpiration" - "jenkinsClientLongExpiration" + "jenkins-client-tester" + "jenkinsClientTesterForRotation" + "jenkins-client-no-expiration" + "jenkins-client-short-expiration" + "jenkins-client-medium-expiration" + "jenkins-client-long-expiration" "ras-test-client" ) diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-disable-register-users-redirect.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-disable-register-users-redirect.groovy index b7f9b916..117a0f8e 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-disable-register-users-redirect.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-disable-register-users-redirect.groovy @@ -44,7 +44,7 @@ pipeline { sed -i \'/REGISTER_USERS_ON/d\' fence_config_tmp.yaml; sed -i \'/REGISTERED_USERS_GROUP/d\' fence_config_tmp.yaml # Update the secret - g3kubectl get secret fence-config -o json | jq --arg new_config "$(cat fence_config_tmp.yaml | base64)" \'.data["fence-config.yaml"]=$new_config\' | g3kubectl apply -f - + kubectl get secret fence-config -o json | jq --arg new_config "$(cat fence_config_tmp.yaml | base64)" \'.data["fence-config.yaml"]=$new_config\' | kubectl apply -f - # Roll Fence rm fence_config_tmp.yaml; gen3 roll fence; gen3 kube-setup-portal diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-enable-register-users-redirect.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-enable-register-users-redirect.groovy index f0d3be13..e3b360f4 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-enable-register-users-redirect.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-enable-register-users-redirect.groovy @@ -29,7 +29,7 @@ pipeline { } stage('Fence Enable Register Users Redirect') { steps { - dir("fence-enable-user-register-redirect") { + dir("ci-only-fence-enable-user-register-redirect") { script { sh '''#!/bin/bash +x set -e @@ -45,7 +45,7 @@ pipeline { echo "REGISTERED_USERS_GROUP: 'data_uploaders'" >> "fence_config_tmp.yaml" # Update the secret - g3kubectl get secret fence-config -o json | jq --arg new_config "$(cat fence_config_tmp.yaml | base64)" \'.data["fence-config.yaml"]=$new_config\' | g3kubectl apply -f - + kubectl get secret fence-config -o json | jq --arg new_config "$(cat fence_config_tmp.yaml | base64)" \'.data["fence-config.yaml"]=$new_config\' | kubectl apply -f - # Roll Fence rm fence_config_tmp.yaml; gen3 roll fence; gen3 kube-setup-portal diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-force-link-google.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-force-link-google.groovy index 52fdd46e..e1f3864e 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-force-link-google.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fence-force-link-google.groovy @@ -34,7 +34,7 @@ pipeline { } stage('Force Link Google Account') { steps { - dir("force_link_google"){ + dir("ci-only-force_link_google"){ script { sh '''#!/bin/bash +x set -e diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fetch-configs.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fetch-configs.groovy index 839890f7..fe6331e1 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fetch-configs.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-fetch-configs.groovy @@ -109,7 +109,7 @@ spec: export GEN3_HOME=\$WORKSPACE/cloud-automation export KUBECTL_NAMESPACE=\${NAMESPACE} source \$GEN3_HOME/gen3/gen3setup.sh - RESULT=`g3kubectl get configmaps manifest-all -o json | jq -r '.data.json'` + RESULT=`kubectl get configmaps manifest-all -o json | jq -r '.data.json'` echo "\$RESULT" > manifest.json ''' } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-generate-api-key.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-generate-api-key.groovy index f7c825a5..db8d0170 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-generate-api-key.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-generate-api-key.groovy @@ -105,7 +105,7 @@ spec: } stage('Generate API Key') { steps { - dir("generate-api-key") { + dir("ci-only-generate-api-key") { script { sh '''#!/bin/bash +x set -e @@ -141,7 +141,7 @@ spec: } post { always { - archiveArtifacts artifacts: 'generate-api-key/*.json' + archiveArtifacts artifacts: 'ci-only-generate-api-key/*.json' } } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-kube-setup-service.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-kube-setup-service.groovy index 24fedc27..300a3adc 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-kube-setup-service.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-kube-setup-service.groovy @@ -37,7 +37,7 @@ pipeline { timeout(time: 5, unit: 'MINUTES') // timeout on this stage } steps { - dir("kube-setup-service"){ + dir("ci-only-kube-setup-service"){ script { try { sh '''#!/bin/bash +x diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-modify-env-for-service-pr.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-modify-env-for-service-pr.groovy index 2a0a7966..d93e2329 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-modify-env-for-service-pr.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-modify-env-for-service-pr.groovy @@ -157,7 +157,7 @@ spec: export KUBECTL_NAMESPACE=\${NAMESPACE} source $GEN3_HOME/gen3/gen3setup.sh gen3 job run usersync ADD_DBGAP true - g3kubectl wait --for=condition=complete --timeout=-1s jobs/usersync + kubectl wait --for=condition=complete --timeout=-1s jobs/usersync ''' } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-modify-env-for-test-repo-pr.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-modify-env-for-test-repo-pr.groovy index 1f5827c8..a05d2a58 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-modify-env-for-test-repo-pr.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-modify-env-for-test-repo-pr.groovy @@ -138,7 +138,7 @@ spec: export KUBECTL_NAMESPACE=\${NAMESPACE} source $GEN3_HOME/gen3/gen3setup.sh gen3 job run usersync ADD_DBGAP true - g3kubectl wait --for=condition=complete --timeout=-1s jobs/usersync + kubectl wait --for=condition=complete --timeout=-1s jobs/usersync ''' } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-revoke-arborist-policy.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-revoke-arborist-policy.groovy index 20213751..a32d0d37 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-revoke-arborist-policy.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-revoke-arborist-policy.groovy @@ -31,7 +31,7 @@ pipeline { } stage('Revoke Arborist Policy') { steps { - dir("revoke-arborist-policy"){ + dir("ci-only-revoke-arborist-policy"){ script { sh '''#!/bin/bash +x set -e diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-run-gen3-command.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-run-gen3-command.groovy index e3ec574b..07651fc3 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-run-gen3-command.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-run-gen3-command.groovy @@ -104,7 +104,7 @@ spec: } stage('Run command on adminvm') { steps { - dir("run-command") { + dir("ci-only-run-command") { script { sh '''#!/bin/bash +x set -e @@ -121,7 +121,7 @@ spec: } post { always { - archiveArtifacts artifacts: 'run-command/result.txt' + archiveArtifacts artifacts: 'ci-only-run-command/result.txt' } } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-run-gen3-job.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-run-gen3-job.groovy index c41f8fa8..47ccc72e 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-run-gen3-job.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-run-gen3-job.groovy @@ -107,7 +107,7 @@ spec: } stage('Run Gen3 job') { steps { - dir("run-gen3-job") { + dir("ci-only-run-gen3-job") { script { sh '''#!/bin/bash +x set -e @@ -118,7 +118,7 @@ spec: gen3 roll all fi gen3 job run \${JOB_NAME} - g3kubectl wait --for=condition=complete --timeout=-1s jobs/\${JOB_NAME} + kubectl wait --for=condition=complete --timeout=-1s jobs/\${JOB_NAME} gen3 job logs \${JOB_NAME} > log.txt ''' } @@ -128,7 +128,7 @@ spec: } post { always { - archiveArtifacts artifacts: 'run-gen3-job/log.txt' + archiveArtifacts artifacts: 'ci-only-run-gen3-job/log.txt' } } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-save-pod-logs.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-save-pod-logs.groovy index 48b25985..4806570e 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-save-pod-logs.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-save-pod-logs.groovy @@ -101,7 +101,7 @@ spec: } stage('Save pod logs') { steps { - dir("save-pod-logs") { + dir("ci-only-save-pod-logs") { script { sh '''#!/bin/bash +x set -e @@ -118,7 +118,7 @@ spec: } post { always { - archiveArtifacts artifacts: 'save-pod-logs/*.log.gz' + archiveArtifacts artifacts: 'ci-only-save-pod-logs/*.log.gz' } } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-select-and-lock-namespace.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-select-and-lock-namespace.groovy index c55f9b16..ee47691d 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-select-and-lock-namespace.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-select-and-lock-namespace.groovy @@ -106,7 +106,7 @@ spec: } stage('Select and lock namespace') { steps { - dir("select-and-lock-namespace") { + dir("ci-only-select-and-lock-namespace") { script { sh '''#!/bin/bash +x export GEN3_HOME=\$WORKSPACE/cloud-automation @@ -146,7 +146,7 @@ spec: } post { always { - archiveArtifacts artifacts: 'select-and-lock-namespace/namespace.txt' + archiveArtifacts artifacts: 'ci-only-select-and-lock-namespace/namespace.txt' } } } diff --git a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-unlock-namespace.groovy b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-unlock-namespace.groovy index 7e4b59d6..cfbdfaa0 100644 --- a/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-unlock-namespace.groovy +++ b/gen3-integration-tests/gen3_ci/jenkins_jobs/ci-only-unlock-namespace.groovy @@ -105,7 +105,7 @@ spec: } stage('Unlock namespace') { steps { - dir("unlock-namespace") { + dir("ci-only-unlock-namespace") { script { sh '''#!/bin/bash +x set -e diff --git a/gen3-integration-tests/pages/login.py b/gen3-integration-tests/pages/login.py index e9a2138d..c0b15854 100644 --- a/gen3-integration-tests/pages/login.py +++ b/gen3-integration-tests/pages/login.py @@ -72,8 +72,6 @@ def login( ) # printing cookies if needed for debugging purposes cookies = page.context.cookies() - for cookie in cookies: - logger.info(f"{cookie['name']}={cookie['value']}") expect(page.locator(self.LOGIN_BUTTON_LIST)).to_be_visible(timeout=10000) if idp == "ORCID": self.orcid_login(page) diff --git a/gen3-integration-tests/pyproject.toml b/gen3-integration-tests/pyproject.toml index 6df0f5a2..b1242ccd 100644 --- a/gen3-integration-tests/pyproject.toml +++ b/gen3-integration-tests/pyproject.toml @@ -43,7 +43,7 @@ addopts = "--log-cli-level=ERROR" markers = [ # general "wip: marks tests as `Work In Progress` and skips them in CI pipeline", - "requires_fence_client: tests for clients related test cases", + "requires_fence_client: tests for fence clients", # services "audit: tests for audit-service", "fence: test for fence service", diff --git a/gen3-integration-tests/services/fence.py b/gen3-integration-tests/services/fence.py index e317512f..c25bb7da 100644 --- a/gen3-integration-tests/services/fence.py +++ b/gen3-integration-tests/services/fence.py @@ -361,32 +361,6 @@ def get_version(self, user="main_account"): assert "version" in response.json().keys() return response.json()["version"] - def get_client_id_secret(self, client_name): - """Gets the fence client information from TEST_DATA_PATH_OBJECT/fence_client folder""" - path = TEST_DATA_PATH_OBJECT / "fence_clients" / "clients_creds.txt" - clients_dict = {} - - with open(path, "r") as file: - for line in file: - # Strip whitespace and skip empty lines - line = line.strip() - if not line: - continue - - # Split line into key and value - if ":" in line: - key, value = line.split(":", 1) - key = key.strip() - value = value.strip() - - clients_dict[key] = value - assert ( - client_name in clients_dict.keys() - ), f"{client_name} not found in {clients_dict.keys()}" - client_info = clients_dict[client_name].split(",") - client_id, client_secret = client_info[0], client_info[1] - return client_id, client_secret - def link_google_account(self, user: str, expires_in: int = None): """Links google account with user account with expiration if provided""" auth = Gen3Auth(refresh_token=pytest.api_keys[user], endpoint=self.BASE_URL) diff --git a/gen3-integration-tests/tests/test_centralized_auth.py b/gen3-integration-tests/tests/test_centralized_auth.py index b219fa75..ad5190e1 100644 --- a/gen3-integration-tests/tests/test_centralized_auth.py +++ b/gen3-integration-tests/tests/test_centralized_auth.py @@ -5,13 +5,12 @@ import os import pytest -from cdislogging import get_logger +from utils import logger from uuid import uuid4 from services.indexd import Indexd from services.fence import Fence from playwright.sync_api import Page -logger = get_logger(__name__, log_level=os.getenv("LOG_LEVEL", "info")) """ NOTES: @@ -143,12 +142,17 @@ def setup_class(cls): new_abc_records["delete_me"]["did"] = str(uuid4()) # Generate Client id and secrets - cls.basic_test_client_id, cls.basic_test_client_secret = ( - cls.fence.get_client_id_secret(client_name="basic-test-client") - ) - cls.basic_test_abc_client_id, cls.basic_test_abc_client_secret = ( - cls.fence.get_client_id_secret(client_name="basic-test-abc-client") - ) + cls.basic_test_client_id = pytest.clients["basic-test-client"]["client_id"] + cls.basic_test_client_secret = pytest.clients["basic-test-client"][ + "client_secret" + ] + + cls.basic_test_abc_client_id = pytest.clients["basic-test-abc-client"][ + "client_id" + ] + cls.basic_test_abc_client_secret = pytest.clients["basic-test-abc-client"][ + "client_secret" + ] # Create indexd records for key, val in indexed_files.items(): diff --git a/gen3-integration-tests/tests/test_client_credentials.py b/gen3-integration-tests/tests/test_client_credentials.py index b3813354..a6744ce8 100644 --- a/gen3-integration-tests/tests/test_client_credentials.py +++ b/gen3-integration-tests/tests/test_client_credentials.py @@ -33,9 +33,8 @@ def test_client_credentials(self): requestor = Requestor() # creating a new client for the test - client_id, client_secret = fence.get_client_id_secret( - client_name="jenkinsClientTester" - ) + client_id = pytest.clients["jenkins-client-tester"]["client_id"] + client_secret = pytest.clients["jenkins-client-tester"]["client_secret"] gen3auth = Gen3Auth( endpoint=pytest.root_url, diff --git a/gen3-integration-tests/tests/test_oauth2.py b/gen3-integration-tests/tests/test_oauth2.py index 2e06ca20..40f1684a 100644 --- a/gen3-integration-tests/tests/test_oauth2.py +++ b/gen3-integration-tests/tests/test_oauth2.py @@ -10,15 +10,11 @@ from services.fence import Fence from pages.login import LoginPage -from utils.gen3_admin_tasks import create_fence_client +from utils import logger -from cdislogging import get_logger from playwright.sync_api import Page -logger = get_logger(__name__, log_level=os.getenv("LOG_LEVEL", "info")) - - @pytest.mark.fence @pytest.mark.requires_fence_client class TestOauth2: @@ -27,12 +23,17 @@ class TestOauth2: @classmethod def setup_class(cls): # Generate Client id and secrets - cls.basic_test_client_id, cls.basic_test_client_secret = ( - cls.fence.get_client_id_secret(client_name="basic-test-client") - ) - cls.implicit_test_client_id, cls.implicit_test_client_secret = ( - cls.fence.get_client_id_secret(client_name="implicit-test-client") - ) + cls.basic_test_client_id = pytest.clients["basic-test-client"]["client_id"] + cls.basic_test_client_secret = pytest.clients["basic-test-client"][ + "client_secret" + ] + + cls.implicit_test_client_id = pytest.clients["implicit-test-client"][ + "client_id" + ] + cls.implicit_test_client_secret = pytest.clients["implicit-test-client"][ + "client_secret" + ] def test_authorization_code_no_user_consent_fail_code_generation(self, page: Page): """ diff --git a/gen3-integration-tests/tests/test_oidc_client.py b/gen3-integration-tests/tests/test_oidc_client.py new file mode 100644 index 00000000..f2472063 --- /dev/null +++ b/gen3-integration-tests/tests/test_oidc_client.py @@ -0,0 +1,177 @@ +import pytest +import os + +from utils import logger +from gen3.auth import Gen3Auth +from gen3.index import Gen3Index +import utils.gen3_admin_tasks as gat + + +@pytest.mark.fence +@pytest.mark.requires_fence_client +class TestOIDCClient: + def test_oidc_client_expiration(self): + """ + Scenario: Test OIDC Client Expiration + Steps: + 1. Create clients with various expiration times and with client_type = client_credentials + 2. Get client_id and client_secrets after each create request and store it + 3. Run `fence-delete-expired-clients` gen3job and check the logs for confirmation + """ + clients = { + "jenkins-client-no-expiration": pytest.clients[ + "jenkins-client-no-expiration" + ], + "jenkins-client-short-expiration": pytest.clients[ + "jenkins-client-short-expiration" + ], + "jenkins-client-medium-expiration": pytest.clients[ + "jenkins-client-medium-expiration" + ], + "jenkins-client-long-expiration": pytest.clients[ + "jenkins-client-long-expiration" + ], + } + for client_name, client_details in clients.items(): + # checking if the access_token is created with client_id and client_secret + gen3auth = Gen3Auth( + endpoint=pytest.root_url, + client_credentials=( + client_details["client_id"], + client_details["client_secret"], + ), + ) + client_access_token = gen3auth.get_access_token() + assert client_access_token, "Client access token was not created" + + # running fence-delete-expired-clients job + gat.run_gen3_job(pytest.namespace, "fence-delete-expired-clients") + # checking the logs from the job pod + job_logs = gat.check_job_pod( + pytest.namespace, "fence-delete-expired-clients", "gen3job" + ) + logs_contents = job_logs["logs.txt"] + logger.debug(f"Logs: {logs_contents}") + + # assertion from logs + assert ( + "jenkins-client-no-expiration" not in logs_contents + ), "jenkins-client-no-expiration found in logs" + assert ( + "Some expired OIDC clients have been deleted!" in logs_contents + ), 'Msg: "Some expired OIDC clients have been deleted!" not found in logs' + assert ( + "jenkins-client-short-expiration" in logs_contents + ), "jenkins-client-short-expiration not found in logs" + assert ( + "Some OIDC clients are expiring soon!" in logs_contents + ), 'Msg: "Some OIDC clients are expiring soon!" not found in logs' + assert ( + "jenkins-client-medium-expiration" in logs_contents + ), "jenkins-client-medium-expiration not found in logs" + assert ( + "jenkins-client-long-expiration" not in logs_contents + ), "jenkins-client-long-expiration found in logs" + + # Testing if the non-expired clients still work properly + for client_name, client_details in clients.items(): + client_id, client_secret = ( + client_details["client_id"], + client_details["client_secret"], + ) + # you shouldnt be able to get access_token for client jenkins-client-short-expiration + if client_name != "jenkins-client-short-expiration": + gen3auth = Gen3Auth( + endpoint=pytest.root_url, + client_credentials=(client_id, client_secret), + ) + client_token = gen3auth.get_access_token() + logger.debug( + f"Access Token for client {client_name} after running fence job : {client_token}" + ) + assert ( + client_token + ), f"Failed to get access token for client_id {client_id}" + else: + # expected result for client jenkins-client-short-expiration + logger.info("Access Token is not found") + + def test_oidc_client_rotation(self): + """ + Scenario: Test OIDC Client Rotation + Steps: + 1. Create client `jenkins-client-tester` with client_type = client_credentials and store it as creds1 + 2. Request client credentials rotation and new credentials as creds2 + 3. Get access_token with help of client_credentials creds1 and cred2 + 4. Send indexd post request to add indexd record and check if it successful request + """ + client_name = "jenkins-client-tester" + logger.info(f"Getting client_id and client_secret for client {client_name} ...") + client_id = pytest.clients[client_name]["client_id"] + client_secret = pytest.clients[client_name]["client_secret"] + logger.info(client_id, client_secret) + + # Client is rotated as part of the setup, to enable test execution in parallel for this test suite. + # Rotated client_id and client_secret are retrieved from pytest.rotated_clients. + client_rotate_id = pytest.rotated_clients[client_name]["client_id"] + client_rotate_secret = pytest.rotated_clients[client_name]["client_secret"] + logger.info(client_rotate_id, client_rotate_secret) + + # Get access_token with client_id and client_secret before running client-fence-rotate command + gen3auth_before = Gen3Auth( + endpoint=pytest.root_url, + client_credentials=(client_id, client_secret), + ) + client_access_token = gen3auth_before.get_access_token() + logger.debug( + f"Client access token before client rotation : {client_access_token}" + ) + assert client_access_token, "Client access token was not created" + + # Get access_token with client_id and client_secret after running client-fence-rotate + gen3auth_after = Gen3Auth( + endpoint=pytest.root_url, + client_credentials=(client_rotate_id, client_rotate_secret), + ) + client_rotate_access_token = gen3auth_after.get_access_token() + logger.debug( + f"Client access token after client rotation : {client_rotate_access_token}" + ) + assert client_rotate_access_token, "Client access token was not created" + + data = { + "file_name": "testfile", + "size": 9, + "hashes": {"md5": "73d643ec3f4beb9020eef0beed440ad0"}, + "urls": ["s3://mybucket/testfile"], + "authz": ["/programs/jnkns/projects/jenkins"], + } + # sending indexd request with access_token before running client-fence-rotate + index_before = Gen3Index(auth_provider=gen3auth_before) + logger.info( + "Creating index record with client creds before client rotation ... " + ) + record1 = index_before.create_record( + hashes=data["hashes"], + urls=data["urls"], + file_name=data["file_name"], + size=data["size"], + authz=data["authz"], + ) + logger.debug(f'Indexd Record created with did : {record1["did"]}') + assert record1["did"], "Indexd record not created successfully" + + # sending indexd request with access_token after running client-fence-rotate + index_after = Gen3Index(auth_provider=gen3auth_after) + logger.info( + "Creating index record with client creds after client rotation ... " + ) + record2 = index_after.create_record( + hashes=data["hashes"], + urls=data["urls"], + file_name=data["file_name"], + size=data["size"], + authz=data["authz"], + ) + logger.debug(f'Indexd Record created with did : {record2["did"]}') + assert record2["did"], "Indexd record not created successfully" diff --git a/gen3-integration-tests/utils/gen3_admin_tasks.py b/gen3-integration-tests/utils/gen3_admin_tasks.py index 1ae9bdc6..3152df1b 100644 --- a/gen3-integration-tests/utils/gen3_admin_tasks.py +++ b/gen3-integration-tests/utils/gen3_admin_tasks.py @@ -133,7 +133,7 @@ def check_job_pod( if build_num: status = job.wait_for_build_completion(build_num) if status == "Completed": - return job.get_build_result(build_num) + return {"logs.txt": job.get_artifact_content(build_num, "logs.txt")} else: job.terminate_build(build_num) raise Exception("Build timed out. Consider increasing max_duration") @@ -169,6 +169,30 @@ def create_fence_client( raise Exception("Build number not found") +def fence_client_rotate(test_env_namespace: str): + """ + Runs jenkins job to create a fence client + Since this requires adminvm interaction we use jenkins. + """ + job = JenkinsJob( + os.getenv("JENKINS_URL"), + os.getenv("JENKINS_USERNAME"), + os.getenv("JENKINS_PASSWORD"), + "ci-only-fence-client-rotate", + ) + params = {"NAMESPACE": test_env_namespace} + build_num = job.build_job(params) + if build_num: + status = job.wait_for_build_completion(build_num) + if status == "Completed": + return job.get_artifact_content(build_num, "client_rotate_creds.txt") + else: + job.terminate_build(build_num) + raise Exception("Build timed out. Consider increasing max_duration") + else: + raise Exception("Build number not found") + + def force_link_google(test_env_namespace: str, username: str, email: str): """ Runs jenkins job to force link google account diff --git a/gen3-integration-tests/utils/test_setup.py b/gen3-integration-tests/utils/test_setup.py index d5611ef4..4ec1d8e2 100644 --- a/gen3-integration-tests/utils/test_setup.py +++ b/gen3-integration-tests/utils/test_setup.py @@ -1,6 +1,7 @@ import json import os import pytest +import re from utils import logger from pathlib import Path @@ -53,5 +54,54 @@ def get_fence_client_info(): outfile.write(data) +def get_client_id_secret(): + """Gets the fence client information from TEST_DATA_PATH_OBJECT/fence_client folder""" + path = TEST_DATA_PATH_OBJECT / "fence_clients" / "clients_creds.txt" + if not os.path.exists(path): + logger.info('clients_creds.txt doesn\'t exists.') + return + with open(path, "r") as file: + content = file.read() + + for entry in content.split("\n"): + if len(entry) == 0: # Empty line + continue + client_name, client_details = entry.split(":") + client_id, client_secret = re.sub(r"[\'()]", "", client_details).split(", ") + pytest.clients[client_name] = { + "client_id": client_id, + "client_secret": client_secret, + } + + def delete_all_fence_clients(): gen3_admin_tasks.delete_fence_client(pytest.namespace) + + +def get_fence_rotated_client_info(): + # Create the client and return the client information + data = gen3_admin_tasks.fence_client_rotate(test_env_namespace=pytest.namespace) + path = TEST_DATA_PATH_OBJECT / "fence_clients" + path.mkdir(parents=True, exist_ok=True) + file_path = path / "client_rotate_creds.txt" + with open(file_path, "w") as outfile: + outfile.write(data) + + +def get_rotated_client_id_secret(): + path = TEST_DATA_PATH_OBJECT / "fence_clients" / "client_rotate_creds.txt" + if not os.path.exists(path): + logger.info('client_rotate_creds.txt doesn\'t exists.') + return + with open(path, "r") as file: + content = file.read() + + for entry in content.split("\n"): + if len(entry) == 0: # Empty line + continue + client_name, client_details = entry.split(":") + client_id, client_secret = re.sub(r"[\'()]", "", client_details).split(", ") + pytest.rotated_clients[client_name] = { + "client_id": client_id, + "client_secret": client_secret, + }