Merge pull request #144 from sartography/fix-git-ssh-creds
backend: fix use of SSH private key for git ops
This commit is contained in:
commit
7f966f39b9
|
@ -55,6 +55,14 @@ if [[ "${SPIFFWORKFLOW_BACKEND_RUN_DATA_SETUP:-}" != "false" ]]; then
|
||||||
SPIFFWORKFLOW_BACKEND_FAIL_ON_INVALID_PROCESS_MODELS=false poetry run python bin/save_all_bpmn.py
|
SPIFFWORKFLOW_BACKEND_FAIL_ON_INVALID_PROCESS_MODELS=false poetry run python bin/save_all_bpmn.py
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY:-}" ]]; then
|
||||||
|
if [[ -z "${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH}" ]]; then
|
||||||
|
export SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH=$(mktemp /tmp/ssh_private_key.XXXXXX)
|
||||||
|
fi
|
||||||
|
chmod 600 "${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH}"
|
||||||
|
echo "${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY}" >"${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Assure that the the Process Models Directory is initialized as a git repo
|
# Assure that the the Process Models Directory is initialized as a git repo
|
||||||
git init "${SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR}"
|
git init "${SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR}"
|
||||||
git config --global --add safe.directory "${SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR}"
|
git config --global --add safe.directory "${SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR}"
|
||||||
|
|
|
@ -12,17 +12,9 @@ set -o errtrace -o errexit -o nounset -o pipefail
|
||||||
bpmn_models_absolute_dir="$1"
|
bpmn_models_absolute_dir="$1"
|
||||||
git_commit_message="$2"
|
git_commit_message="$2"
|
||||||
git_branch="$3"
|
git_branch="$3"
|
||||||
git_commit_username="$4"
|
|
||||||
git_commit_email="$5"
|
|
||||||
git_commit_password="$6"
|
|
||||||
|
|
||||||
if [[ -z "${5:-}" ]]; then
|
if [[ -z "${3:-}" ]]; then
|
||||||
>&2 echo "usage: $(basename "$0") [bpmn_models_absolute_dir] [git_commit_message] [git_branch] [git_commit_username] [git_commit_email]"
|
>&2 echo "usage: $(basename "${0}") [bpmn_models_absolute_dir] [git_commit_message] [git_branch]"
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$git_commit_password" && -z "${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY:-}" ]]; then
|
|
||||||
>&2 echo "ERROR: A git password or SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY must be provided"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -32,38 +24,20 @@ function failed_to_get_lock() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
cd "$bpmn_models_absolute_dir"
|
cd "${bpmn_models_absolute_dir}"
|
||||||
git add .
|
git add .
|
||||||
|
|
||||||
# https://unix.stackexchange.com/a/155077/456630
|
# https://unix.stackexchange.com/a/155077/456630
|
||||||
if [ -z "$(git status --porcelain)" ]; then
|
if [ -z "$(git status --porcelain)" ]; then
|
||||||
echo "No changes to commit"
|
echo "No changes to commit"
|
||||||
else
|
return
|
||||||
|
|
||||||
git config --local user.name "$git_commit_username"
|
|
||||||
git config --local user.email "$git_commit_email"
|
|
||||||
|
|
||||||
if [[ -n "${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY:-}" ]]; then
|
|
||||||
tmpfile=$(mktemp /tmp/tmp_git.XXXXXX)
|
|
||||||
chmod 600 "$tmpfile"
|
|
||||||
echo "$SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY" >"$tmpfile"
|
|
||||||
export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${tmpfile} -F /dev/null"
|
|
||||||
else
|
|
||||||
PAT="${git_commit_username}:${git_commit_password}"
|
|
||||||
AUTH=$(echo -n "$PAT" | openssl base64 | tr -d '\n')
|
|
||||||
git config --local http.extraHeader "Authorization: Basic $AUTH"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
git commit -m "$git_commit_message"
|
git commit -m "${git_commit_message}"
|
||||||
git push --set-upstream origin "$git_branch"
|
git push --set-upstream origin "${git_branch}"
|
||||||
|
|
||||||
if [[ -z "${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY:-}" ]]; then
|
|
||||||
git config --unset --local http.extraHeader
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exec {lock_fd}>/var/lock/mylockfile || failed_to_get_lock
|
exec {lock_fd}>/var/lock/spiff-workflow-git-lock || failed_to_get_lock
|
||||||
flock --timeout 60 "$lock_fd" || failed_to_get_lock
|
flock --timeout 60 "${lock_fd}" || failed_to_get_lock
|
||||||
run
|
run
|
||||||
flock -u "$lock_fd"
|
flock -u "${lock_fd}"
|
||||||
|
|
|
@ -96,9 +96,6 @@ SPIFFWORKFLOW_BACKEND_GIT_PUBLISH_CLONE_URL = environ.get(
|
||||||
SPIFFWORKFLOW_BACKEND_GIT_COMMIT_ON_SAVE = (
|
SPIFFWORKFLOW_BACKEND_GIT_COMMIT_ON_SAVE = (
|
||||||
environ.get("SPIFFWORKFLOW_BACKEND_GIT_COMMIT_ON_SAVE", default="false") == "true"
|
environ.get("SPIFFWORKFLOW_BACKEND_GIT_COMMIT_ON_SAVE", default="false") == "true"
|
||||||
)
|
)
|
||||||
SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY = environ.get(
|
|
||||||
"SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY"
|
|
||||||
)
|
|
||||||
SPIFFWORKFLOW_BACKEND_GIT_USERNAME = environ.get("SPIFFWORKFLOW_BACKEND_GIT_USERNAME")
|
SPIFFWORKFLOW_BACKEND_GIT_USERNAME = environ.get("SPIFFWORKFLOW_BACKEND_GIT_USERNAME")
|
||||||
SPIFFWORKFLOW_BACKEND_GIT_USER_EMAIL = environ.get(
|
SPIFFWORKFLOW_BACKEND_GIT_USER_EMAIL = environ.get(
|
||||||
"SPIFFWORKFLOW_BACKEND_GIT_USER_EMAIL"
|
"SPIFFWORKFLOW_BACKEND_GIT_USER_EMAIL"
|
||||||
|
@ -106,11 +103,8 @@ SPIFFWORKFLOW_BACKEND_GIT_USER_EMAIL = environ.get(
|
||||||
SPIFFWORKFLOW_BACKEND_GITHUB_WEBHOOK_SECRET = environ.get(
|
SPIFFWORKFLOW_BACKEND_GITHUB_WEBHOOK_SECRET = environ.get(
|
||||||
"SPIFFWORKFLOW_BACKEND_GITHUB_WEBHOOK_SECRET", default=None
|
"SPIFFWORKFLOW_BACKEND_GITHUB_WEBHOOK_SECRET", default=None
|
||||||
)
|
)
|
||||||
SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY = environ.get(
|
SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH = environ.get(
|
||||||
"SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY", default=None
|
"SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH", default=None
|
||||||
)
|
|
||||||
SPIFFWORKFLOW_BACKEND_GIT_USER_PASSWORD = environ.get(
|
|
||||||
"SPIFFWORKFLOW_BACKEND_GIT_USER_PASSWORD", default=None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Database Configuration
|
# Database Configuration
|
||||||
|
|
|
@ -94,19 +94,7 @@ class GitService:
|
||||||
raise ConfigurationError(
|
raise ConfigurationError(
|
||||||
"SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR config must be set"
|
"SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR config must be set"
|
||||||
)
|
)
|
||||||
if current_app.config["SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY"]:
|
|
||||||
os.environ["SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY"] = (
|
|
||||||
current_app.config["SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY"]
|
|
||||||
)
|
|
||||||
|
|
||||||
git_username = ""
|
|
||||||
git_email = ""
|
|
||||||
if (
|
|
||||||
current_app.config["SPIFFWORKFLOW_BACKEND_GIT_USERNAME"]
|
|
||||||
and current_app.config["SPIFFWORKFLOW_BACKEND_GIT_USER_EMAIL"]
|
|
||||||
):
|
|
||||||
git_username = current_app.config["SPIFFWORKFLOW_BACKEND_GIT_USERNAME"]
|
|
||||||
git_email = current_app.config["SPIFFWORKFLOW_BACKEND_GIT_USER_EMAIL"]
|
|
||||||
shell_command_path = os.path.join(
|
shell_command_path = os.path.join(
|
||||||
current_app.root_path, "..", "..", "bin", "git_commit_bpmn_models_repo"
|
current_app.root_path, "..", "..", "bin", "git_commit_bpmn_models_repo"
|
||||||
)
|
)
|
||||||
|
@ -115,9 +103,6 @@ class GitService:
|
||||||
repo_path_to_use,
|
repo_path_to_use,
|
||||||
message,
|
message,
|
||||||
branch_name_to_use,
|
branch_name_to_use,
|
||||||
git_username,
|
|
||||||
git_email,
|
|
||||||
current_app.config["SPIFFWORKFLOW_BACKEND_GIT_USER_PASSWORD"],
|
|
||||||
]
|
]
|
||||||
return cls.run_shell_command_to_get_stdout(shell_command)
|
return cls.run_shell_command_to_get_stdout(shell_command)
|
||||||
|
|
||||||
|
@ -169,8 +154,17 @@ class GitService:
|
||||||
cls, command: list[str], return_success_state: bool = False
|
cls, command: list[str], return_success_state: bool = False
|
||||||
) -> Union[subprocess.CompletedProcess[bytes], bool]:
|
) -> Union[subprocess.CompletedProcess[bytes], bool]:
|
||||||
"""Run_shell_command."""
|
"""Run_shell_command."""
|
||||||
|
env = {
|
||||||
|
'GIT_COMMITTER_NAME': current_app.config.get("SPIFFWORKFLOW_BACKEND_GIT_USERNAME", "unknown"),
|
||||||
|
'GIT_COMMITTER_EMAIL': current_app.config.get("SPIFFWORKFLOW_BACKEND_GIT_USER_EMAIL", "unknown@example.org"),
|
||||||
|
}
|
||||||
|
# SSH authentication can be also provided via gitconfig.
|
||||||
|
ssh_key_path = current_app.config.get("SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH")
|
||||||
|
if ssh_key_path is not None:
|
||||||
|
env['GIT_SSH_COMMAND'] = 'ssh -F /dev/null -i %s' % ssh_key_path
|
||||||
|
|
||||||
# this is fine since we pass the commands directly
|
# this is fine since we pass the commands directly
|
||||||
result = subprocess.run(command, check=False, capture_output=True) # noqa
|
result = subprocess.run(command, check=False, capture_output=True, env=env) # noqa
|
||||||
if return_success_state:
|
if return_success_state:
|
||||||
return result.returncode == 0
|
return result.returncode == 0
|
||||||
|
|
||||||
|
@ -231,7 +225,7 @@ class GitService:
|
||||||
with FileSystemService.cd(
|
with FileSystemService.cd(
|
||||||
current_app.config["SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR"]
|
current_app.config["SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR"]
|
||||||
):
|
):
|
||||||
cls.run_shell_command(["git", "pull"])
|
cls.run_shell_command(["git", "pull", "--rebase"])
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -252,11 +246,6 @@ class GitService:
|
||||||
git_clone_url = current_app.config[
|
git_clone_url = current_app.config[
|
||||||
"SPIFFWORKFLOW_BACKEND_GIT_PUBLISH_CLONE_URL"
|
"SPIFFWORKFLOW_BACKEND_GIT_PUBLISH_CLONE_URL"
|
||||||
]
|
]
|
||||||
if git_clone_url.startswith("https://"):
|
|
||||||
git_clone_url = git_clone_url.replace(
|
|
||||||
"https://",
|
|
||||||
f"https://{current_app.config['SPIFFWORKFLOW_BACKEND_GIT_USERNAME']}:{current_app.config['SPIFFWORKFLOW_BACKEND_GIT_USER_PASSWORD']}@",
|
|
||||||
)
|
|
||||||
cmd = ["git", "clone", git_clone_url, destination_process_root]
|
cmd = ["git", "clone", git_clone_url, destination_process_root]
|
||||||
|
|
||||||
cls.run_shell_command(cmd)
|
cls.run_shell_command(cmd)
|
||||||
|
|
Loading…
Reference in New Issue