Compare commits
5 Commits
1c62aa50fa
...
543f9b64ec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
543f9b64ec | ||
|
|
90048cd869 | ||
|
|
24d21b052f | ||
|
|
12388473e2 | ||
|
|
23fae1d7f2 |
@@ -1,7 +1,7 @@
|
||||
# doc: https://developers.openai.com/codex/config-advanced
|
||||
# https://developers.openai.com/codex/config-reference
|
||||
|
||||
# The API key was valid just for a week, now it's supposed to be valid for a year
|
||||
# The API key should be valid for a year
|
||||
# Generate API key:
|
||||
# 1. Open https://apex.oraclecorp.com/pls/apex/r/oca/api-key/home and generate an API Key for yourself.
|
||||
# 2. Press 'Copy Codex Environment Setup Command'
|
||||
@@ -33,6 +33,7 @@ model_reasoning_effort = "medium"
|
||||
|
||||
[features]
|
||||
multi_agent = true
|
||||
goals = true
|
||||
# remote_control = true
|
||||
|
||||
[agents]
|
||||
@@ -41,6 +42,7 @@ max_depth = 2
|
||||
|
||||
[tui]
|
||||
alternate_screen = "always"
|
||||
status_line = ["model-with-reasoning", "current-dir", "git-branch", "run-state", "codex-version", "context-remaining"]
|
||||
|
||||
[tui.model_availability_nux]
|
||||
"gpt-5.5" = 4
|
||||
@@ -176,6 +178,13 @@ personality = "pragmatic"
|
||||
model_reasoning_effort = "high"
|
||||
plan_mode_reasoning_effort = "high"
|
||||
|
||||
[profiles.gpt-5-5.features]
|
||||
terminal_resize_reflow = true
|
||||
memories = false
|
||||
external_migration = false
|
||||
goals = true
|
||||
prevent_idle_sleep = false
|
||||
|
||||
[profiles.gpt-5-5-pro]
|
||||
model = "gpt-5.5-pro"
|
||||
model_provider = "oca-responses"
|
||||
@@ -194,6 +203,18 @@ approval_mode = "approve"
|
||||
[mcp_servers.playwright.tools.browser_resize]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.playwright.tools.browser_fill_form]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.playwright.tools.browser_click]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.playwright.tools.browser_type]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.playwright.tools.browser_tabs]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.oci-kb]
|
||||
command = "/Users/jetpac/.local/bin/ocikb-mcp-server"
|
||||
startup_timeout_sec = 30.0
|
||||
@@ -275,6 +296,15 @@ approval_mode = "approve"
|
||||
[mcp_servers.devops_mcp.tools.get_shepherd_execution_target_state]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.devops_mcp.tools.get_tenancy_by_id]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.devops_mcp.tools.list_subscription_mappings]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.devops_mcp.tools.list_subscriptions]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_shepherd]
|
||||
command = "uvx"
|
||||
args = ["--default-index", "https://artifactory.oci.oraclecorp.com/api/pypi/global-release-pypi/simple/", "--from", "mcp-shepherd-server", "mcp-shepherd", "--transport", "stdio"]
|
||||
@@ -331,6 +361,15 @@ approval_mode = "approve"
|
||||
[mcp_servers.mcp_shepherd.tools.shepherd_get_release_target_log]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_shepherd.tools.shepherd_get_raw_phase_one_result]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_shepherd.tools.shepherd_get_latest_static_analysis_for_execution_target]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_shepherd.tools.shepherd_get_release_phase_target_guardrails_metadata]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.grt]
|
||||
command = "/Users/jetpac/.codex/bin/grt-mcp"
|
||||
startup_timeout_sec = 30.0
|
||||
@@ -426,6 +465,12 @@ approval_mode = "approve"
|
||||
[mcp_servers.central_confluence.tools.confluence_search]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.central_confluence.tools.confluence_get_macro_hints]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.central_confluence.tools.confluence_search_user]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.notmuch]
|
||||
command = "node"
|
||||
args = ["/Users/jetpac/Documents/codex-tools/MCPs/notmuch/dist/index.js"]
|
||||
@@ -462,41 +507,31 @@ command = "node"
|
||||
args = ["/Users/jetpac/Documents/codex-tools/MCPs/jenkins/dist/index.js"]
|
||||
startup_timeout_sec = 30.0
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_get_job]
|
||||
approval_mode = "approve"
|
||||
# Anything not explicitly overridden will ask.
|
||||
default_tools_approval_mode = "prompt"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_get_build]
|
||||
approval_mode = "approve"
|
||||
[mcp_servers.jenkins.tools]
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_get_log]
|
||||
approval_mode = "approve"
|
||||
# [mcp_servers.jenkins.tools.jenkins_find_builds]
|
||||
jenkins_compare_builds = { approval_mode = "approve" }
|
||||
jenkins_download_log = { approval_mode = "approve" }
|
||||
jenkins_find_builds = { approval_mode = "approve" }
|
||||
jenkins_get_build = { approval_mode = "approve" }
|
||||
jenkins_get_changes = { approval_mode = "approve" }
|
||||
jenkins_get_input_actions = { approval_mode = "approve" }
|
||||
jenkins_get_job = { approval_mode = "approve" }
|
||||
jenkins_get_job_config = { approval_mode = "approve" }
|
||||
jenkins_get_log = { approval_mode = "approve" }
|
||||
jenkins_get_node = { approval_mode = "approve" }
|
||||
jenkins_get_queue_item = { approval_mode = "approve" }
|
||||
jenkins_get_stage_log = { approval_mode = "approve" }
|
||||
jenkins_get_test_results = { approval_mode = "approve" }
|
||||
jenkins_list_jobs = { approval_mode = "approve" }
|
||||
jenkins_list_nodes = { approval_mode = "approve" }
|
||||
jenkins_search_console = { approval_mode = "approve" }
|
||||
jenkins_validate_jenkinsfile = { approval_mode = "approve" }
|
||||
jenkins_watch_build = { approval_mode = "approve" }
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_get_changes]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_search_console]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_get_stage_log]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_watch_build]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_get_input_actions]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_get_node]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_download_log]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_get_job_config]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.jenkins.tools.jenkins_find_builds]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.vm]
|
||||
command = "node"
|
||||
@@ -523,7 +558,7 @@ BITBUCKET_ENABLE_READ_ONLY = "true"
|
||||
BITBUCKET_ENABLE_SAFE_WRITE = "true"
|
||||
BITBUCKET_URL = "https://bitbucket.oci.oraclecorp.com"
|
||||
MCP_PROJECT_DEFAULT = "ODAAS"
|
||||
MCP_PROJECT_LIST = "ODAAS"
|
||||
MCP_PROJECT_LIST = "ODAAS,CARE"
|
||||
|
||||
[mcp_servers.oracle-bitbucket.tools.get_activities]
|
||||
approval_mode = "approve"
|
||||
@@ -555,6 +590,9 @@ approval_mode = "approve"
|
||||
[mcp_servers.oracle-bitbucket.tools.search]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.oracle-bitbucket.tools.browse_repository]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp-atlassian]
|
||||
command = "uvx"
|
||||
args = ["--python=3.11", "mcp-atlassian"]
|
||||
@@ -836,8 +874,77 @@ trust_level = "trusted"
|
||||
[projects."/Users/jetpac/PycharmProjects/solaris-cluster/common/MCPs/bugdb_mcp"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/OSD/tigera-v1.40.9/tigera-operator-new"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/codex/2026-05-04/lang-correction-hi-joe-in-the"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/codex/2026-05-04/hi-joe-in-the-akidr-we"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/private/tmp/email"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/private/tmp/mcp-test"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/private/tmp/codex-test"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/akidr/tmp-test"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/akidr/akidr-sso-fix"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/private/tmp/crowdstrike"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/kubernetes-x250"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/private/tmp/new"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/.oci"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/akidr/aru-client"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/private/tmp/merge-marian/oci-desktop-service-shepherd"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/akidr/ips-repo-pkg-delivery"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/OSD/guardrails-skill"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/11.4.93"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/OSD/merino"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/codex"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/private/tmp/hjovno"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/codex/update-solarisx86-linux"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/Documents/codex/symphony"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[projects."/Users/jetpac/src/symphony"]
|
||||
trust_level = "trusted"
|
||||
|
||||
[marketplaces.openai-bundled]
|
||||
last_updated = "2026-04-29T14:50:30Z"
|
||||
last_updated = "2026-05-05T21:54:34Z"
|
||||
source_type = "local"
|
||||
source = "/Users/jetpac/.codex/.tmp/bundled-marketplaces/openai-bundled"
|
||||
|
||||
@@ -846,9 +953,6 @@ last_updated = "2026-04-28T18:12:08Z"
|
||||
source_type = "local"
|
||||
source = "/Users/jetpac/.cache/codex-runtimes/codex-primary-runtime/plugins/openai-primary-runtime"
|
||||
|
||||
[plugins."browser-use@openai-bundled"]
|
||||
enabled = true
|
||||
|
||||
[plugins."documents@openai-primary-runtime"]
|
||||
enabled = true
|
||||
|
||||
@@ -858,6 +962,9 @@ enabled = true
|
||||
[plugins."presentations@openai-primary-runtime"]
|
||||
enabled = true
|
||||
|
||||
[plugins."browser-use@openai-bundled"]
|
||||
enabled = true
|
||||
|
||||
# [projects."/Users/jetpac/Documents/codex-tools/MCPs/ident-scm-mcp"]
|
||||
# trust_level = "trusted"
|
||||
|
||||
@@ -920,3 +1027,66 @@ approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.buildservice__buildservice_auth_status]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_security_findings_for_team]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.jirasd__jira_get_issue_dates]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.jirasd__jira_get_transitions]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.jirasd__jira_get_issue]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_realms]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_regions]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__list_tenancy_regions]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__list_shepherd_flock_configs]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.jira__jira_get_issue_development_info]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_shepherd_flocks]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_shepherd_releases]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_shepherd_release_details]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_shepherd_release_phase_target_guardrails_metadata]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__list_shepherd_execution_targets_for_flock]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_shepherd_phase_execution_targets]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__get_shepherd_release_target_blocker]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__list_shepherd_system_settings]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.devops__list_shepherd_system_setting_names]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.jirasd__jira_search]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.sks__search]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.mcp_gateway.tools.kcm__search]
|
||||
approval_mode = "approve"
|
||||
|
||||
@@ -1077,6 +1077,7 @@ before packages are loaded."
|
||||
"~/Documents/org/work/oracle.org"
|
||||
"~/Documents/org/someday.org"
|
||||
"~/Documents/org/calendar.org"
|
||||
"~/Documents/organice/telefon.org"
|
||||
))
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Host bitbucket.oci.oraclecorp.com
|
||||
HostkeyAlgorithms +ssh-rsa
|
||||
PubkeyAcceptedAlgorithms +ssh-rsa
|
||||
|
||||
Host dabel dabel.us.oracle.com andel andel.us.oracle.com gates gates.us.oracle.com on10-patch.us.oracle.com
|
||||
Host dabel dabel.us.oracle.com andel andel.us.oracle.com gates gates.us.oracle.com on10-patch.us.oracle.com scapen*
|
||||
User pnyc
|
||||
IdentityFile ~/.ssh/dabel.key
|
||||
RequestTTY yes
|
||||
@@ -17,3 +17,35 @@ Host codex.webad1phx.solarisx86phx.oraclevcn.com
|
||||
User pnyc
|
||||
IdentityFile ~/.ssh/id_rsa
|
||||
IdentitiesOnly yes
|
||||
|
||||
Host operator-access-token.svc.ad1.r2
|
||||
User pnyc
|
||||
|
||||
Host jenkins-java-test
|
||||
HostName 100.106.196.24
|
||||
User opc
|
||||
IdentityFile ~/.ssh/id_rsa
|
||||
IdentitiesOnly yes
|
||||
WarnWeakCrypto no
|
||||
|
||||
Host nginx-osd-dev
|
||||
HostName 100.106.197.175
|
||||
User opc
|
||||
IdentityFile ~/.ssh/osd-dev-pnyc
|
||||
IdentitiesOnly yes
|
||||
WarnWeakCrypto no
|
||||
|
||||
Host osd-calico-dev
|
||||
HostName 100.106.197.237
|
||||
User opc
|
||||
IdentityFile ~/.ssh/id_ed25519
|
||||
IdentitiesOnly yes
|
||||
WarnWeakCrypto no
|
||||
|
||||
Host pnyc-ws
|
||||
HostName 100.106.196.59
|
||||
User opc
|
||||
IdentityFile ~/.ssh/id_pnyc-ws
|
||||
IdentitiesOnly yes
|
||||
WarnWeakCrypto no
|
||||
ForwardAgent yes
|
||||
@@ -160,9 +160,15 @@ Host adam-test
|
||||
HostName 100.106.212.188
|
||||
User opc
|
||||
|
||||
Host nori nori.commonsub.zsphx.oraclevcn.com
|
||||
Hostname nori.commonsub.zsphx.oraclevcn.com
|
||||
User opc
|
||||
# Host nori nori.commonsub.zsphx.oraclevcn.com
|
||||
# Hostname nori.commonsub.zsphx.oraclevcn.com
|
||||
# User opc
|
||||
|
||||
Host nori sfzfs-nori.commonsub.zsphx.oraclevcn.com
|
||||
Hostname sfzfs-nori.commonsub.zsphx.oraclevcn.com
|
||||
User opc
|
||||
IdentityFile ~/.ssh/nori
|
||||
|
||||
|
||||
# Host operator-access-token.svc.ad1.r2 bastion*.oracleiaas.com
|
||||
# Include ~/.ssh/ssh_configs/config
|
||||
|
||||
5
bin/codex-wrapper.sh
Executable file
5
bin/codex-wrapper.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
export BITBUCKET_TOKEN=NzQ0MDE3NjEzNDE1Oh6PpMt8Rl+a569vzoPOfCRJ+Kwt
|
||||
"$HOME/bin/codex-devops-auth.sh" -a on-request -s danger-full-access "$@"
|
||||
|
||||
258
bin/load-yubikey-piv-ssh
Executable file
258
bin/load-yubikey-piv-ssh
Executable file
@@ -0,0 +1,258 @@
|
||||
#!/bin/zsh
|
||||
# Load YubiKey PIV SSH keys into the macOS launchd-managed ssh-agent.
|
||||
# The default health check verifies the PIV AUTH key with ssh-add -T so
|
||||
# listed-but-stale PKCS#11 keys are reloaded instead of being trusted.
|
||||
set -u
|
||||
|
||||
PKCS11_LIB="${PKCS11_LIB:-/usr/local/lib/opensc-pkcs11.so}"
|
||||
PIV_KEY_PATTERN="${PIV_KEY_PATTERN:-PIV AUTH pubkey|SIGN pubkey|KEY MAN pubkey|CARD AUTH pubkey}"
|
||||
PIV_AUTH_PATTERN="${PIV_AUTH_PATTERN:-PIV AUTH pubkey}"
|
||||
VERIFY_MODE="auth"
|
||||
TMP_DIRS=()
|
||||
SCRIPT_NAME="${0:t}"
|
||||
|
||||
usage() {
|
||||
# Print the small CLI surface; normal operation intentionally has few knobs.
|
||||
cat <<EOF
|
||||
Usage: ${SCRIPT_NAME} [--no-verify] [--help]
|
||||
|
||||
Safely load YubiKey PIV keys into the macOS launchd ssh-agent.
|
||||
|
||||
Options:
|
||||
--no-verify Only check whether PIV keys are listed in the agent.
|
||||
--help Show this help.
|
||||
|
||||
Environment:
|
||||
PKCS11_LIB PKCS#11 provider path. Default: /usr/local/lib/opensc-pkcs11.so
|
||||
EOF
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--no-verify)
|
||||
VERIFY_MODE="none"
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print -u2 -- "load-yubikey-piv-ssh: unknown option: $1"
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
cleanup() {
|
||||
# Remove temporary public-key files created for ssh-add -T verification.
|
||||
local dir
|
||||
for dir in "${TMP_DIRS[@]}"; do
|
||||
[[ -n "${dir}" && -d "${dir}" ]] && rm -rf -- "${dir}"
|
||||
done
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
die() {
|
||||
# Report a fatal script error with a stable prefix for shell output.
|
||||
print -u2 -- "load-yubikey-piv-ssh: $*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
note() {
|
||||
# Emit status messages to stderr so stdout stays clean for callers.
|
||||
print -u2 -- "load-yubikey-piv-ssh: $*"
|
||||
}
|
||||
|
||||
agent_socket() {
|
||||
# Return the launchd-published ssh-agent socket if it exists.
|
||||
local sock
|
||||
sock="$(launchctl getenv SSH_AUTH_SOCK 2>/dev/null || true)"
|
||||
[[ -n "${sock}" && -S "${sock}" ]] || return 1
|
||||
print -r -- "${sock}"
|
||||
}
|
||||
|
||||
use_launchd_agent() {
|
||||
# Force this shell to use Apple's launchd-managed agent socket and ignore
|
||||
# stale SSH_AGENT_PID values from manually started agents.
|
||||
local sock
|
||||
sock="$(agent_socket)" || die "could not find launchd SSH_AUTH_SOCK"
|
||||
export SSH_AUTH_SOCK="${sock}"
|
||||
unset SSH_AGENT_PID
|
||||
}
|
||||
|
||||
agent_has_piv_keys() {
|
||||
# Check for any listed YubiKey PIV identities in the active agent.
|
||||
ssh-add -l 2>/dev/null | egrep -q "${PIV_KEY_PATTERN}"
|
||||
}
|
||||
|
||||
loaded_piv_public_keys() {
|
||||
# Select loaded public keys for either health verification or no-verify mode.
|
||||
local pattern
|
||||
case "${VERIFY_MODE}" in
|
||||
auth) pattern="${PIV_AUTH_PATTERN}" ;;
|
||||
none) pattern="${PIV_KEY_PATTERN}" ;;
|
||||
*) die "internal error: unknown verify mode: ${VERIFY_MODE}" ;;
|
||||
esac
|
||||
|
||||
ssh-add -L 2>/dev/null | egrep "${pattern}" || true
|
||||
}
|
||||
|
||||
verify_loaded_piv_keys() {
|
||||
# Export the loaded PIV AUTH public key to a temp file and ask ssh-add to
|
||||
# perform a local sign-and-verify operation through the agent.
|
||||
[[ "${VERIFY_MODE}" == "none" ]] && return 0
|
||||
|
||||
local tmp key_file line count
|
||||
local -a key_files
|
||||
|
||||
tmp="$(mktemp -d "${TMPDIR:-/tmp}/load-yubikey-piv-ssh.XXXXXX")" ||
|
||||
die "failed to create temporary directory"
|
||||
TMP_DIRS+=("${tmp}")
|
||||
|
||||
count=0
|
||||
while IFS= read -r line; do
|
||||
[[ -n "${line}" ]] || continue
|
||||
count=$((count + 1))
|
||||
key_file="${tmp}/piv-${count}.pub"
|
||||
print -r -- "${line}" >| "${key_file}" ||
|
||||
die "failed to write temporary public key"
|
||||
chmod 600 "${key_file}" || die "failed to chmod temporary public key"
|
||||
key_files+=("${key_file}")
|
||||
done < <(loaded_piv_public_keys)
|
||||
|
||||
if [[ "${count}" -eq 0 ]]; then
|
||||
note "no matching PIV AUTH public key found for verification"
|
||||
return 1
|
||||
fi
|
||||
|
||||
SSH_ASKPASS_REQUIRE=never ssh-add -T "${key_files[@]}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
agent_has_healthy_piv_keys() {
|
||||
# A healthy state requires both listed PIV keys and a successful sign test.
|
||||
if ! agent_has_piv_keys; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if verify_loaded_piv_keys; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
agent_responds() {
|
||||
# Treat "no identities" as a working agent, but reject broken sockets.
|
||||
ssh-add -l >/dev/null 2>&1
|
||||
case "$?" in
|
||||
0|1) return 0 ;; # 1 means a reachable agent with no identities.
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
restart_launchd_agent() {
|
||||
# Restart only the launchd-managed ssh-agent. macOS may block kickstart under
|
||||
# SIP, so fall back to terminating the exact PID reported by launchctl.
|
||||
local pid
|
||||
local i
|
||||
|
||||
note "restarting launchd ssh-agent"
|
||||
|
||||
if launchctl kickstart -k "gui/${UID}/com.openssh.ssh-agent" >/dev/null 2>&1; then
|
||||
sleep 1
|
||||
use_launchd_agent
|
||||
return 0
|
||||
fi
|
||||
|
||||
pid="$(launchctl print "gui/${UID}/com.openssh.ssh-agent" 2>/dev/null |
|
||||
awk '/pid = / { print $3; exit }')"
|
||||
|
||||
if [[ -n "${pid}" ]]; then
|
||||
note "launchctl kickstart failed; terminating launchd ssh-agent pid ${pid}"
|
||||
kill -TERM "${pid}" >/dev/null 2>&1 ||
|
||||
die "failed to terminate launchd ssh-agent pid ${pid}"
|
||||
|
||||
for i in {1..10}; do
|
||||
kill -0 "${pid}" >/dev/null 2>&1 || break
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
if kill -0 "${pid}" >/dev/null 2>&1; then
|
||||
note "launchd ssh-agent pid ${pid} did not exit after TERM; sending KILL"
|
||||
kill -KILL "${pid}" >/dev/null 2>&1 ||
|
||||
die "failed to kill launchd ssh-agent pid ${pid}"
|
||||
fi
|
||||
else
|
||||
note "launchctl kickstart failed and no running launchd ssh-agent pid was found"
|
||||
fi
|
||||
|
||||
use_launchd_agent
|
||||
|
||||
if ! agent_responds; then
|
||||
die "failed to restart launchd ssh-agent"
|
||||
fi
|
||||
}
|
||||
|
||||
load_provider() {
|
||||
# Load the OpenSC PKCS#11 provider and force PIN entry on the terminal.
|
||||
SSH_ASKPASS_REQUIRE=never ssh-add -s "${PKCS11_LIB}"
|
||||
}
|
||||
|
||||
verify_or_report_stale() {
|
||||
# Treat listed PIV keys as healthy only after verification succeeds.
|
||||
if agent_has_healthy_piv_keys; then
|
||||
case "${VERIFY_MODE}" in
|
||||
none) note "PIV keys are already loaded" ;;
|
||||
auth) note "PIV AUTH key is already loaded and verified" ;;
|
||||
esac
|
||||
return 0
|
||||
fi
|
||||
|
||||
if agent_has_piv_keys; then
|
||||
note "PIV keys are listed but failed verification; treating agent as stale"
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
[[ -r "${PKCS11_LIB}" ]] || die "PKCS#11 library is not readable: ${PKCS11_LIB}"
|
||||
|
||||
use_launchd_agent
|
||||
|
||||
if verify_or_report_stale; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if agent_has_piv_keys; then
|
||||
restart_launchd_agent
|
||||
elif ! agent_responds; then
|
||||
restart_launchd_agent
|
||||
fi
|
||||
|
||||
if load_provider && agent_has_healthy_piv_keys; then
|
||||
case "${VERIFY_MODE}" in
|
||||
none) note "PIV keys loaded" ;;
|
||||
auth) note "PIV keys loaded and PIV AUTH key verified" ;;
|
||||
esac
|
||||
exit 0
|
||||
fi
|
||||
|
||||
note "initial load failed; checking agent state"
|
||||
|
||||
if verify_or_report_stale; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
restart_launchd_agent
|
||||
|
||||
if load_provider && agent_has_healthy_piv_keys; then
|
||||
case "${VERIFY_MODE}" in
|
||||
none) note "PIV keys loaded after agent restart" ;;
|
||||
auth) note "PIV keys loaded after agent restart and PIV AUTH key verified" ;;
|
||||
esac
|
||||
exit 0
|
||||
fi
|
||||
|
||||
die "failed to load and verify PIV keys"
|
||||
Reference in New Issue
Block a user