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:
Kevin Burnett 2023-02-21 11:19:48 -08:00 committed by GitHub
commit 7f966f39b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 69 deletions

View File

@ -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
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
git init "${SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR}"
git config --global --add safe.directory "${SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR}"

View File

@ -12,17 +12,9 @@ set -o errtrace -o errexit -o nounset -o pipefail
bpmn_models_absolute_dir="$1"
git_commit_message="$2"
git_branch="$3"
git_commit_username="$4"
git_commit_email="$5"
git_commit_password="$6"
if [[ -z "${5:-}" ]]; then
>&2 echo "usage: $(basename "$0") [bpmn_models_absolute_dir] [git_commit_message] [git_branch] [git_commit_username] [git_commit_email]"
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"
if [[ -z "${3:-}" ]]; then
>&2 echo "usage: $(basename "${0}") [bpmn_models_absolute_dir] [git_commit_message] [git_branch]"
exit 1
fi
@ -32,38 +24,20 @@ function failed_to_get_lock() {
}
function run() {
cd "$bpmn_models_absolute_dir"
cd "${bpmn_models_absolute_dir}"
git add .
# https://unix.stackexchange.com/a/155077/456630
if [ -z "$(git status --porcelain)" ]; then
echo "No changes to commit"
else
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
git commit -m "$git_commit_message"
git push --set-upstream origin "$git_branch"
if [[ -z "${SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY:-}" ]]; then
git config --unset --local http.extraHeader
fi
return
fi
git commit -m "${git_commit_message}"
git push --set-upstream origin "${git_branch}"
}
exec {lock_fd}>/var/lock/mylockfile || failed_to_get_lock
flock --timeout 60 "$lock_fd" || 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
run
flock -u "$lock_fd"
flock -u "${lock_fd}"

View File

@ -96,9 +96,6 @@ SPIFFWORKFLOW_BACKEND_GIT_PUBLISH_CLONE_URL = environ.get(
SPIFFWORKFLOW_BACKEND_GIT_COMMIT_ON_SAVE = (
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_USER_EMAIL = environ.get(
"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", default=None
)
SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY = environ.get(
"SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY", default=None
)
SPIFFWORKFLOW_BACKEND_GIT_USER_PASSWORD = environ.get(
"SPIFFWORKFLOW_BACKEND_GIT_USER_PASSWORD", default=None
SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH = environ.get(
"SPIFFWORKFLOW_BACKEND_GIT_SSH_PRIVATE_KEY_PATH", default=None
)
# Database Configuration

View File

@ -94,19 +94,7 @@ class GitService:
raise ConfigurationError(
"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(
current_app.root_path, "..", "..", "bin", "git_commit_bpmn_models_repo"
)
@ -115,9 +103,6 @@ class GitService:
repo_path_to_use,
message,
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)
@ -169,8 +154,17 @@ class GitService:
cls, command: list[str], return_success_state: bool = False
) -> Union[subprocess.CompletedProcess[bytes], bool]:
"""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
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:
return result.returncode == 0
@ -178,9 +172,9 @@ class GitService:
stdout = result.stdout.decode("utf-8")
stderr = result.stderr.decode("utf-8")
raise GitCommandError(
f"Failed to execute git command: {command} "
f"Stdout: {stdout} "
f"Stderr: {stderr} "
f"Failed to execute git command: {command}"
f"Stdout: {stdout}"
f"Stderr: {stderr}"
)
return result
@ -231,7 +225,7 @@ class GitService:
with FileSystemService.cd(
current_app.config["SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR"]
):
cls.run_shell_command(["git", "pull"])
cls.run_shell_command(["git", "pull", "--rebase"])
return True
@classmethod
@ -252,11 +246,6 @@ class GitService:
git_clone_url = current_app.config[
"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]
cls.run_shell_command(cmd)