GetAPIKeyFromHelper executes a shell command to dynamically generate an API key. The command is executed in cmd.exe with a timeout controlled by the provided context. It returns the trimmed output from stdout, or an error if the command fails. On timeout, it terminates the entire Job Object (cmd.ex
(ctx context.Context, helperCmd string)
| 70 | // |
| 71 | // Security note: The returned API key is sensitive and should not be logged. |
| 72 | func GetAPIKeyFromHelper(ctx context.Context, helperCmd string) (string, error) { |
| 73 | if helperCmd == "" { |
| 74 | return "", errors.New("api_key_helper command is empty") |
| 75 | } |
| 76 | |
| 77 | // Create context with timeout if not already set |
| 78 | if _, hasDeadline := ctx.Deadline(); !hasDeadline { |
| 79 | var cancel context.CancelFunc |
| 80 | ctx, cancel = context.WithTimeout(ctx, HelperTimeout) |
| 81 | defer cancel() |
| 82 | } |
| 83 | |
| 84 | // Execute command in cmd.exe |
| 85 | cmd := exec.CommandContext(ctx, "cmd.exe", "/c", helperCmd) |
| 86 | |
| 87 | // Use CREATE_NEW_PROCESS_GROUP and CREATE_BREAKAWAY_FROM_JOB flags |
| 88 | // This allows the child process to be assigned to a new Job, |
| 89 | // even if the parent process is already in a Job |
| 90 | cmd.SysProcAttr = &syscall.SysProcAttr{ |
| 91 | CreationFlags: windows.CREATE_NEW_PROCESS_GROUP | windows.CREATE_BREAKAWAY_FROM_JOB, |
| 92 | } |
| 93 | |
| 94 | var stdout, stderr bytes.Buffer |
| 95 | cmd.Stdout = &stdout |
| 96 | cmd.Stderr = &stderr |
| 97 | |
| 98 | // Create Job Object first |
| 99 | job, err := createKillOnCloseJob() |
| 100 | if err != nil { |
| 101 | return "", fmt.Errorf("create job failed: %w", err) |
| 102 | } |
| 103 | // With KILL_ON_JOB_CLOSE, closing the job will kill all processes |
| 104 | defer func() { |
| 105 | _ = windows.CloseHandle(job) |
| 106 | }() |
| 107 | |
| 108 | // Start the child process |
| 109 | if err = cmd.Start(); err != nil { |
| 110 | return "", fmt.Errorf("api_key_helper start failed: %w", err) |
| 111 | } |
| 112 | |
| 113 | // Assign child process to Job |
| 114 | hProc, err := assignProcessToJob(job, cmd.Process.Pid) |
| 115 | if err != nil { |
| 116 | // If unable to breakaway due to policy, fall back to just killing the process |
| 117 | // (but this won't guarantee killing grandchild processes) |
| 118 | _ = cmd.Process.Kill() |
| 119 | _ = cmd.Wait() |
| 120 | return "", fmt.Errorf("assign process to job failed: %w", err) |
| 121 | } |
| 122 | defer func() { |
| 123 | _ = windows.CloseHandle(hProc) |
| 124 | }() |
| 125 | |
| 126 | done := make(chan error, 1) |
| 127 | go func() { |
| 128 | done <- cmd.Wait() |
| 129 | }() |
nothing calls this directly
no test coverage detected