diff --git a/bin/installAll.sh b/bin/installAll.sh index 1df61c2..7f0434d 100755 --- a/bin/installAll.sh +++ b/bin/installAll.sh @@ -161,7 +161,6 @@ STARTUP_WAVES=( "mc-infra-connector mc-infra-manager mc-iam-manager mc-iam-manager-post-initial" "mc-data-manager mc-web-console-api mc-web-console-front" "mc-observability-manager mc-observability-front mc-observability-insight mc-observability-insight-scheduler mc-observability-mcp-grafana mc-observability-mcp-maria mc-observability-mcp-influx mc-observability-log-collector" - "mc-workflow-manager-jenkins" "mc-application-manager mc-workflow-manager mc-cost-optimizer-fe" ) @@ -191,17 +190,6 @@ check_post_initial() { fi } -register_jenkins_credentials() { - local bootstrap_script="$PROJECT_ROOT_ABS/tool/jenkins/register-credentials.sh" - - echo "" - echo "Registering Jenkins credentials..." - if ! bash "$bootstrap_script"; then - echo "Error: Jenkins credential registration failed." >&2 - return 1 - fi -} - # ============================================================================= # Save current directory at script start @@ -556,19 +544,12 @@ case $RUN_MODE in wave_num=$((wave_num + 1)) echo "" echo "---- Wave $wave_num/${#STARTUP_WAVES[@]}: $wave_services ----" - if [ "$wave_num" -lt "${#STARTUP_WAVES[@]}" ]; then - ./mcc infra run -d -s "$wave_services" - else - ./mcc infra run -s "$wave_services" - fi + ./mcc infra run -s "$wave_services" run_exit=$? if [ $run_exit -ne 0 ]; then report_run_failure "$run_exit" "Wave $wave_num ($wave_services)" exit 1 fi - if [ "$wave_services" = "mc-workflow-manager-jenkins" ]; then - register_jenkins_credentials || exit 1 - fi done check_post_initial @@ -605,9 +586,6 @@ case $RUN_MODE in report_run_failure "$run_exit" "Wave $wave_num ($wave_services)" exit 1 fi - if [ "$wave_services" = "mc-workflow-manager-jenkins" ]; then - register_jenkins_credentials || exit 1 - fi done echo "" diff --git a/conf/docker/docker-compose.yaml b/conf/docker/docker-compose.yaml index 4a44b6e..7424e9c 100644 --- a/conf/docker/docker-compose.yaml +++ b/conf/docker/docker-compose.yaml @@ -1014,7 +1014,6 @@ services: - /usr/bin/docker:/usr/bin/docker - ./container-volume/mc-workflow-manager/jenkins/:/var/jenkins_home:rw - ./tool/init.groovy.d:/usr/share/jenkins/ref/init.groovy.d - - ./tool/jenkins:/opt/mcmp/jenkins-credentials:ro environment: JENKINS_USERNAME: ${MC_WORKFLOW_MANAGER_JENKINS_USERNAME:-admin} JENKINS_PASSWORD: ${MC_WORKFLOW_MANAGER_JENKINS_PASSWORD:-123456} diff --git a/conf/docker/tool/init.groovy.d/basic-security.groovy b/conf/docker/tool/init.groovy.d/basic-security.groovy index 26d2f66..2c8560e 100644 --- a/conf/docker/tool/init.groovy.d/basic-security.groovy +++ b/conf/docker/tool/init.groovy.d/basic-security.groovy @@ -5,8 +5,6 @@ import hudson.security.* // 설치할 플러그인 목록 def pluginParameter = """ workflow-api -credentials -snakeyaml-api swarm authorize-project antisamy-markup-formatter diff --git a/conf/docker/tool/jenkins/jenkins-credentials.groovy b/conf/docker/tool/jenkins/jenkins-credentials.groovy deleted file mode 100644 index 8a5b1cd..0000000 --- a/conf/docker/tool/jenkins/jenkins-credentials.groovy +++ /dev/null @@ -1,78 +0,0 @@ -if (!binding.hasVariable("encodedCredentialsYaml")) { - throw new IllegalStateException("encodedCredentialsYaml must be provided by the external bootstrap script") -} - -byte[] decryptedBytes = null -String yamlText = null -try { - decryptedBytes = Base64.decoder.decode(encodedCredentialsYaml.toString()) - if (decryptedBytes.length == 0) { - throw new IllegalStateException("CSP credentials are empty") - } - yamlText = new String(decryptedBytes, java.nio.charset.StandardCharsets.UTF_8) -} finally { - if (decryptedBytes != null) { - java.util.Arrays.fill(decryptedBytes, (byte) 0) - } -} - -def yamlRoot = new org.yaml.snakeyaml.Yaml().load(yamlText) -def adminCredentials = yamlRoot?.credentialholder?.admin - -if (!(adminCredentials instanceof Map)) { - throw new IllegalStateException("credentialholder.admin is required in credentials.yaml.enc") -} - -def objectStorageKeys = [ - aws: ["aws_access_key_id", "aws_secret_access_key"], - gcp: ["S3AccessKey", "S3SecretKey"], - alibaba: ["AccessKeyId", "AccessKeySecret"], - tencent: ["SecretId", "SecretKey"], - ibm: ["S3AccessKey", "S3SecretKey"], - ncp: ["ncloud_access_key", "ncloud_secret_key"], - nhn: ["S3AccessKey", "S3SecretKey"] -] - -def store = com.cloudbees.plugins.credentials.SystemCredentialsProvider.instance.store -def domain = com.cloudbees.plugins.credentials.domains.Domain.global() -def registered = [] -def skipped = [] - -objectStorageKeys.each { provider, keys -> - def providerCredentials = adminCredentials[provider] - def accessKey = providerCredentials instanceof Map ? providerCredentials[keys[0]]?.toString()?.trim() : "" - def secretKey = providerCredentials instanceof Map ? providerCredentials[keys[1]]?.toString()?.trim() : "" - - if (!accessKey || !secretKey) { - skipped << provider - return - } - if (accessKey.contains("\n") || accessKey.contains("\r") || secretKey.contains("\n") || secretKey.contains("\r")) { - throw new IllegalStateException("Object Storage credential for ${provider} must not contain line breaks") - } - - def credentialId = "object-storage-credential-${provider}" - def credential = new com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl( - com.cloudbees.plugins.credentials.CredentialsScope.GLOBAL, - credentialId, - "M-CMP Object Storage credential for ${provider.toUpperCase()}", - accessKey, - secretKey - ) - def existing = store.getCredentials(domain).find { it.id == credentialId } - def saved = existing ? store.updateCredentials(domain, existing, credential) : store.addCredentials(domain, credential) - - if (!saved) { - throw new IllegalStateException("Failed to save Jenkins credential ${credentialId}") - } - registered << credentialId -} - -registered.each { println "MCMP_OBJECT_STORAGE_CREDENTIAL_REGISTERED ${it}" } -skipped.each { println "MCMP_OBJECT_STORAGE_CREDENTIAL_SKIPPED ${it}" } -new File(jenkins.model.Jenkins.get().rootDir, ".mcmp-object-storage-credentials-initialized").text = "ready\n" -println "MCMP_OBJECT_STORAGE_CREDENTIALS_COMPLETE" - -yamlText = null -yamlRoot = null -adminCredentials = null diff --git a/conf/docker/tool/jenkins/register-credentials.sh b/conf/docker/tool/jenkins/register-credentials.sh deleted file mode 100755 index c3790a9..0000000 --- a/conf/docker/tool/jenkins/register-credentials.sh +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail -umask 077 - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -readonly SCRIPT_DIR -readonly JENKINS_CONTAINER="${MCMP_JENKINS_CONTAINER_NAME:-mc-workflow-manager-jenkins}" -readonly ENCRYPTED_CREDENTIALS_FILE="${MCMP_CREDENTIALS_FILE:-$HOME/.cloud-barista/credentials.yaml.enc}" -readonly DECRYPT_KEY_FILE="${MCMP_CREDENTIALS_KEY_FILE:-$HOME/.cloud-barista/.tmp_enc_key}" -readonly GROOVY_SCRIPT="$SCRIPT_DIR/jenkins-credentials.groovy" -readonly REGISTRATION_MARKER="/var/jenkins_home/.mcmp-object-storage-credentials-initialized" -readonly MAX_PASSWORD_ATTEMPTS=3 - -MCMP_JENKINS_COOKIE_FILE="" - -cleanup_jenkins_cookie() { - if [ -n "$MCMP_JENKINS_COOKIE_FILE" ]; then - rm -f -- "$MCMP_JENKINS_COOKIE_FILE" - fi -} - -run_inside_container() { - : "${JENKINS_USERNAME:?JENKINS_USERNAME must not be empty}" - : "${JENKINS_PASSWORD:?JENKINS_PASSWORD must not be empty}" - - local jenkins_url="http://localhost:8080" - local crumb_header - - MCMP_JENKINS_COOKIE_FILE=$(mktemp /tmp/mcmp-jenkins-cookie.XXXXXX) - trap cleanup_jenkins_cookie EXIT - - crumb_header=$(curl -fsS \ - --user "$JENKINS_USERNAME:$JENKINS_PASSWORD" \ - --cookie-jar "$MCMP_JENKINS_COOKIE_FILE" \ - "$jenkins_url/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)") - - if [ -z "$crumb_header" ]; then - echo "Error: Jenkins returned an empty CSRF crumb." >&2 - return 1 - fi - - curl -fsS \ - --user "$JENKINS_USERNAME:$JENKINS_PASSWORD" \ - --cookie "$MCMP_JENKINS_COOKIE_FILE" \ - --header "$crumb_header" \ - --data-urlencode "script@-" \ - "$jenkins_url/scriptText" -} - -if [ "${1:-}" = "--inside-container" ]; then - if [ "$#" -ne 1 ]; then - echo "Error: --inside-container does not accept additional arguments." >&2 - exit 1 - fi - run_inside_container - exit $? -fi - -force_registration=false -case "${1:-}" in - "") - ;; - --force) - force_registration=true - ;; - *) - echo "Usage: $0 [--force]" >&2 - exit 1 - ;; -esac - -for command_name in docker openssl; do - if ! command -v "$command_name" >/dev/null 2>&1; then - echo "Error: $command_name is required to register Jenkins credentials." >&2 - exit 1 - fi -done - -if [ ! -f "$GROOVY_SCRIPT" ]; then - echo "Error: Jenkins credential script not found: $GROOVY_SCRIPT" >&2 - exit 1 -fi - -container_running=$(docker inspect --format '{{.State.Running}}' "$JENKINS_CONTAINER" 2>/dev/null || true) -if [ "$container_running" != "true" ]; then - echo "Error: Jenkins container is not running: $JENKINS_CONTAINER" >&2 - exit 1 -fi - -echo "Waiting for Jenkins initialization to complete..." -jenkins_ready=false -for ((attempt = 1; attempt <= 120; attempt++)); do - health_status=$(docker inspect \ - --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' \ - "$JENKINS_CONTAINER" 2>/dev/null || true) - if [ "$health_status" = "healthy" ]; then - jenkins_ready=true - break - fi - sleep 5 -done - -if [ "$jenkins_ready" != "true" ]; then - echo "Error: Jenkins did not become healthy within 10 minutes." >&2 - exit 1 -fi - -if [ "$force_registration" != "true" ] && \ - docker exec "$JENKINS_CONTAINER" test -f "$REGISTRATION_MARKER"; then - echo "Jenkins credentials are already initialized; skipping registration." - exit 0 -fi - -if [ ! -f "$ENCRYPTED_CREDENTIALS_FILE" ] || [ ! -s "$ENCRYPTED_CREDENTIALS_FILE" ]; then - echo "Encrypted CSP credentials not found or empty; skipping Jenkins credential registration:" - echo " $ENCRYPTED_CREDENTIALS_FILE" - echo "Register the credentials manually in the Jenkins UI." - exit 0 -fi - -encoded_credentials_yaml="" -credentials_decrypted=false -if [ -s "$DECRYPT_KEY_FILE" ]; then - echo "Using the host key file for this one-time registration: $DECRYPT_KEY_FILE" - if encoded_credentials_yaml=$( - openssl enc -aes-256-cbc -d -pbkdf2 \ - -in "$ENCRYPTED_CREDENTIALS_FILE" \ - -pass "file:$DECRYPT_KEY_FILE" 2>/dev/null | - openssl base64 -A - ); then - credentials_decrypted=true - else - encoded_credentials_yaml="" - echo "Warning: failed to decrypt credentials.yaml.enc with .tmp_enc_key." >&2 - fi -fi - -if [ "$credentials_decrypted" != "true" ] && [ -t 0 ]; then - for ((attempt = 1; attempt <= MAX_PASSWORD_ATTEMPTS; attempt++)); do - credential_password="" - IFS= read -r -s -p "Enter the credentials.yaml.enc password ($attempt/$MAX_PASSWORD_ATTEMPTS): " credential_password || credential_password="" - printf '\n' - - if [ -z "$credential_password" ]; then - echo "Warning: a decryption password is required ($attempt/$MAX_PASSWORD_ATTEMPTS)." >&2 - continue - fi - - if encoded_credentials_yaml=$( - printf '%s\n' "$credential_password" | - openssl enc -aes-256-cbc -d -pbkdf2 \ - -in "$ENCRYPTED_CREDENTIALS_FILE" \ - -pass stdin 2>/dev/null | - openssl base64 -A - ); then - credentials_decrypted=true - unset credential_password - break - fi - - encoded_credentials_yaml="" - unset credential_password - echo "Warning: failed to decrypt credentials.yaml.enc with the entered password ($attempt/$MAX_PASSWORD_ATTEMPTS)." >&2 - done -fi - -if [ "$credentials_decrypted" != "true" ]; then - echo "Unable to decrypt credentials.yaml.enc; skipping Jenkins credential registration." - echo "Register the credentials manually in the Jenkins UI." - exit 0 -fi - -if [ -z "$encoded_credentials_yaml" ]; then - echo "Error: decrypted CSP credentials are empty." >&2 - exit 1 -fi - -if ! registration_output=$( - { - printf 'encodedCredentialsYaml = "%s"\n' "$encoded_credentials_yaml" - sed -n '1,$p' "$GROOVY_SCRIPT" - } | docker exec -i "$JENKINS_CONTAINER" \ - /opt/mcmp/jenkins-credentials/register-credentials.sh --inside-container -); then - unset encoded_credentials_yaml - echo "Error: failed to send credentials to Jenkins." >&2 - exit 1 -fi -unset encoded_credentials_yaml - -registration_complete=false -while IFS= read -r output_line; do - case "$output_line" in - MCMP_OBJECT_STORAGE_CREDENTIAL_REGISTERED\ *|MCMP_OBJECT_STORAGE_CREDENTIAL_SKIPPED\ *) - printf '%s\n' "$output_line" - ;; - MCMP_OBJECT_STORAGE_CREDENTIALS_COMPLETE) - registration_complete=true - ;; - esac -done <<< "$registration_output" - -if [ "$registration_complete" != "true" ]; then - echo "Error: Jenkins did not confirm credential registration." >&2 - exit 1 -fi - -echo "Jenkins credential registration is complete."