Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
Support SSH public key authentication for submodules (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericb-summit committed Oct 14, 2022
1 parent d1998da commit 1ea4c0b
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ resources:
* `target_branch`(string): Filter merge requests by target_branch. Default is empty string.
* `source_branch`(string): Filter merge requests by source_branch. Default is empty string.
* `sort` (string): Merge requests sorting order, either `asc` (default) or `desc` to reverse.
* `ssh_keys` (string[]): When set to a non-empty array, an ssh-agent will be started and the specified keys will be added to it. This is only relevant for submodules with an ssh URL and passphrase encrypted keys are not supported.
* `recursive`: When set to `true`, will pull submodules by issuing a `git submodule update --init --recursive`. Note that if your submodules are hosted on the same server, be sure to [use a relative path](https://www.gniibe.org/memo/software/git/using-submodule.html) to avoid ssh/https protocol clashing (as the MR is fetched via https, this resource would have no way to authenticate a git+ssh connection).

## Behavior
Expand Down
50 changes: 50 additions & 0 deletions pkg/in/agent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package in

import (
"os"
"os/exec"
"strings"
)

type AgentRunner interface {
Start() error
AddKey(key string) error
}

func NewAgentRunner() AgentRunner {
return &AgentRunnerImpl{
sockPath: "/tmp/ssh-agent.sock",
}
}

type AgentRunnerImpl struct {
sockPath string
agent *exec.Cmd
}

func (r *AgentRunnerImpl) Start() error {
if r.agent != nil {
return nil // already running
}
agent := exec.Command("ssh-agent", "-a", r.sockPath)
agent.Stdin = os.Stdin
agent.Stderr = os.Stderr
err := agent.Run()
if err != nil {
return err
}
r.agent = agent
os.Setenv("SSH_AUTH_SOCK", r.sockPath)
return nil
}

func (r AgentRunnerImpl) AddKey(key string) error {
command := exec.Command("ssh-add", "-")
command.Stderr = os.Stderr
command.Stdin = strings.NewReader(key + "\n") // this trailing newline is mandatory or ssh-add will fail
err := command.Run()
if err != nil {
return err
}
return nil
}
19 changes: 19 additions & 0 deletions pkg/in/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import (
type Command struct {
client *gitlab.Client
runner GitRunner
agent AgentRunner
}

func NewCommand(client *gitlab.Client) *Command {
return &Command{
client,
NewRunner(),
NewAgentRunner(),
}
}

Expand Down Expand Up @@ -69,6 +71,23 @@ func (command *Command) Run(destination string, request Request) (Response, erro
return Response{}, err
}

if (request.Source.SshKeys != nil) && (len(request.Source.SshKeys) != 0) {
err = command.runner.Run("config", "--global", "core.sshCommand", "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no")
if err != nil {
return Response{}, err
}
err = command.agent.Start()
if err != nil {
return Response{}, err
}
for _, key := range request.Source.SshKeys {
err = command.agent.AddKey(key)
if err != nil {
return Response{}, err
}
}
}

os.Chdir(destination)

err = command.runner.Run("remote", "add", "source", source.String())
Expand Down
1 change: 1 addition & 0 deletions pkg/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Source struct {
Sort string `json:"sort,omitempty"`
Paths []string `json:"paths,omitempty"`
IgnorePaths []string `json:"ignore_paths,omitempty"`
SshKeys []string `json:"ssh_keys,omitempty"`
}

type Version struct {
Expand Down

0 comments on commit 1ea4c0b

Please sign in to comment.