Browse Source

Write to SSH config instead of using env

This commit remove the SSH key handling from the git package, instead
writing an SSH config that will be used by git+ssh.

This accomplishes two things:
 1. it decouples the git operations from SSH key handling; and,
 2. it makes using a third-party git library easier, since that won't
 need special SSH key handling either.
Michael Bridgen 1 year ago
parent
commit
317e0792b9
5 changed files with 85 additions and 52 deletions
  1. 13
    1
      Gopkg.lock
  2. 8
    1
      cmd/fluxd/main.go
  3. 33
    39
      git/operations.go
  4. 9
    11
      git/repo.go
  5. 22
    0
      ssh/keygen.go

+ 13
- 1
Gopkg.lock View File

@@ -187,6 +187,12 @@
187 187
   packages = ["."]
188 188
   revision = "5b9ff866471762aa2ab2dced63c9fb6f53921342"
189 189
 
190
+[[projects]]
191
+  name = "github.com/kevinburke/ssh_config"
192
+  packages = ["."]
193
+  revision = "fa48d7ff1cfb9f26c514b80d520880394293bf08"
194
+  version = "0.2"
195
+
190 196
 [[projects]]
191 197
   branch = "master"
192 198
   name = "github.com/kr/logfmt"
@@ -211,6 +217,12 @@
211 217
   revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf"
212 218
   version = "v1.0.0-rc1"
213 219
 
220
+[[projects]]
221
+  name = "github.com/pelletier/go-buffruneio"
222
+  packages = ["."]
223
+  revision = "c37440a7cf42ac63b919c752ca73a85067e05992"
224
+  version = "v0.2.0"
225
+
214 226
 [[projects]]
215 227
   branch = "master"
216 228
   name = "github.com/petar/GoLLRB"
@@ -376,6 +388,6 @@
376 388
 [solve-meta]
377 389
   analyzer-name = "dep"
378 390
   analyzer-version = 1
379
-  inputs-digest = "34df08675550de897967373573c4c8d6d515afb8184badc4e3e44dcec32a2561"
391
+  inputs-digest = "ec725965d5d758e435fde23508d9ffa5984f312e7d99466cea5530461f71a7da"
380 392
   solver-name = "gps-cdcl"
381 393
   solver-version = 1

+ 8
- 1
cmd/fluxd/main.go View File

@@ -191,6 +191,12 @@ func main() {
191 191
 		}
192 192
 
193 193
 		publicKey, privateKeyPath := sshKeyRing.KeyPair()
194
+		// NB this assumes that the private key path will be stable,
195
+		// which is fair since it's mounted from a secret.
196
+		if err = ssh.WriteSSHConfig(privateKeyPath); err != nil {
197
+			logger.Log("err", err)
198
+			os.Exit(1)
199
+		}
194 200
 
195 201
 		logger := log.With(logger, "component", "platform")
196 202
 		logger.Log("identity", privateKeyPath)
@@ -351,8 +357,9 @@ func main() {
351 357
 	{
352 358
 		repo = git.Repo{
353 359
 			GitRemoteConfig: gitRemoteConfig,
354
-			KeyRing:         sshKeyRing,
355 360
 		}
361
+		// TODO: should not need to supply all of this -- maybe just
362
+		// on clone?
356 363
 		gitConfig := git.Config{
357 364
 			SyncTag:   *gitSyncTag,
358 365
 			NotesRef:  *gitNotesRef,

+ 33
- 39
git/operations.go View File

@@ -14,7 +14,6 @@ import (
14 14
 	"context"
15 15
 
16 16
 	"github.com/pkg/errors"
17
-	"github.com/weaveworks/flux/ssh"
18 17
 )
19 18
 
20 19
 func config(ctx context.Context, workingDir, user, email string) error {
@@ -22,21 +21,21 @@ func config(ctx context.Context, workingDir, user, email string) error {
22 21
 		"user.name":  user,
23 22
 		"user.email": email,
24 23
 	} {
25
-		if err := execGitCmd(ctx, workingDir, nil, nil, "config", k, v); err != nil {
24
+		if err := execGitCmd(ctx, workingDir, nil, "config", k, v); err != nil {
26 25
 			return errors.Wrap(err, "setting git config")
27 26
 		}
28 27
 	}
29 28
 	return nil
30 29
 }
31 30
 
32
-func clone(ctx context.Context, workingDir string, keyRing ssh.KeyRing, repoURL, repoBranch string) (path string, err error) {
31
+func clone(ctx context.Context, workingDir string, repoURL, repoBranch string) (path string, err error) {
33 32
 	repoPath := filepath.Join(workingDir, "repo")
34 33
 	args := []string{"clone"}
35 34
 	if repoBranch != "" {
36 35
 		args = append(args, "--branch", repoBranch)
37 36
 	}
38 37
 	args = append(args, repoURL, repoPath)
39
-	if err := execGitCmd(ctx, workingDir, keyRing, nil, args...); err != nil {
38
+	if err := execGitCmd(ctx, workingDir, nil, args...); err != nil {
40 39
 		return "", errors.Wrap(err, "git clone")
41 40
 	}
42 41
 	return repoPath, nil
@@ -45,22 +44,22 @@ func clone(ctx context.Context, workingDir string, keyRing ssh.KeyRing, repoURL,
45 44
 // checkPush sanity-checks that we can write to the upstream repo with
46 45
 // the given keyring (being able to `clone` is an adequate check that
47 46
 // we can read the upstream).
48
-func checkPush(ctx context.Context, keyRing ssh.KeyRing, workingDir, upstream string) error {
47
+func checkPush(ctx context.Context, workingDir, upstream string) error {
49 48
 	// --force just in case we fetched the tag from upstream when cloning
50
-	if err := execGitCmd(ctx, workingDir, nil, nil, "tag", "--force", CheckPushTag); err != nil {
49
+	if err := execGitCmd(ctx, workingDir, nil, "tag", "--force", CheckPushTag); err != nil {
51 50
 		return errors.Wrap(err, "tag for write check")
52 51
 	}
53
-	if err := execGitCmd(ctx, workingDir, keyRing, nil, "push", "--force", upstream, "tag", CheckPushTag); err != nil {
52
+	if err := execGitCmd(ctx, workingDir, nil, "push", "--force", upstream, "tag", CheckPushTag); err != nil {
54 53
 		return errors.Wrap(err, "attempt to push tag")
55 54
 	}
56
-	return execGitCmd(ctx, workingDir, keyRing, nil, "push", "-d", upstream, "tag", CheckPushTag)
55
+	return execGitCmd(ctx, workingDir, nil, "push", "-d", upstream, "tag", CheckPushTag)
57 56
 }
58 57
 
59 58
 func commit(ctx context.Context, workingDir string, commitAction *CommitAction) error {
60 59
 	commitAuthor := commitAction.Author
61 60
 	if commitAuthor != "" {
62 61
 		if err := execGitCmd(ctx,
63
-			workingDir, nil, nil,
62
+			workingDir, nil,
64 63
 			"commit",
65 64
 			"--no-verify", "-a", "--author", commitAuthor, "-m", commitAction.Message,
66 65
 		); err != nil {
@@ -69,7 +68,7 @@ func commit(ctx context.Context, workingDir string, commitAction *CommitAction)
69 68
 		return nil
70 69
 	}
71 70
 	if err := execGitCmd(ctx,
72
-		workingDir, nil, nil,
71
+		workingDir, nil,
73 72
 		"commit",
74 73
 		"--no-verify", "-a", "-m", commitAction.Message,
75 74
 	); err != nil {
@@ -79,24 +78,24 @@ func commit(ctx context.Context, workingDir string, commitAction *CommitAction)
79 78
 }
80 79
 
81 80
 // push the refs given to the upstream repo
82
-func push(ctx context.Context, keyRing ssh.KeyRing, workingDir, upstream string, refs []string) error {
81
+func push(ctx context.Context, workingDir, upstream string, refs []string) error {
83 82
 	args := append([]string{"push", upstream}, refs...)
84
-	if err := execGitCmd(ctx, workingDir, keyRing, nil, args...); err != nil {
83
+	if err := execGitCmd(ctx, workingDir, nil, args...); err != nil {
85 84
 		return errors.Wrap(err, fmt.Sprintf("git push %s %s", upstream, refs))
86 85
 	}
87 86
 	return nil
88 87
 }
89 88
 
90 89
 // pull the specific ref from upstream
91
-func pull(ctx context.Context, keyRing ssh.KeyRing, workingDir, upstream, ref string) error {
92
-	if err := execGitCmd(ctx, workingDir, keyRing, nil, "pull", "--ff-only", upstream, ref); err != nil {
90
+func pull(ctx context.Context, workingDir, upstream, ref string) error {
91
+	if err := execGitCmd(ctx, workingDir, nil, "pull", "--ff-only", upstream, ref); err != nil {
93 92
 		return errors.Wrap(err, fmt.Sprintf("git pull --ff-only %s %s", upstream, ref))
94 93
 	}
95 94
 	return nil
96 95
 }
97 96
 
98
-func fetch(ctx context.Context, keyRing ssh.KeyRing, workingDir, upstream, refspec string) error {
99
-	if err := execGitCmd(ctx, workingDir, keyRing, nil, "fetch", "--tags", upstream, refspec); err != nil &&
97
+func fetch(ctx context.Context, workingDir, upstream, refspec string) error {
98
+	if err := execGitCmd(ctx, workingDir, nil, "fetch", "--tags", upstream, refspec); err != nil &&
100 99
 		!strings.Contains(err.Error(), "Couldn't find remote ref") {
101 100
 		return errors.Wrap(err, fmt.Sprintf("git fetch --tags %s %s", upstream, refspec))
102 101
 	}
@@ -104,7 +103,7 @@ func fetch(ctx context.Context, keyRing ssh.KeyRing, workingDir, upstream, refsp
104 103
 }
105 104
 
106 105
 func refExists(ctx context.Context, workingDir, ref string) (bool, error) {
107
-	if err := execGitCmd(ctx, workingDir, nil, nil, "rev-list", ref); err != nil {
106
+	if err := execGitCmd(ctx, workingDir, nil, "rev-list", ref); err != nil {
108 107
 		if strings.Contains(err.Error(), "unknown revision") {
109 108
 			return false, nil
110 109
 		}
@@ -116,7 +115,7 @@ func refExists(ctx context.Context, workingDir, ref string) (bool, error) {
116 115
 // Get the full ref for a shorthand notes ref.
117 116
 func getNotesRef(ctx context.Context, workingDir, ref string) (string, error) {
118 117
 	out := &bytes.Buffer{}
119
-	if err := execGitCmd(ctx, workingDir, nil, out, "notes", "--ref", ref, "get-ref"); err != nil {
118
+	if err := execGitCmd(ctx, workingDir, out, "notes", "--ref", ref, "get-ref"); err != nil {
120 119
 		return "", err
121 120
 	}
122 121
 	return strings.TrimSpace(out.String()), nil
@@ -127,13 +126,13 @@ func addNote(ctx context.Context, workingDir, rev, notesRef string, note *Note)
127 126
 	if err != nil {
128 127
 		return err
129 128
 	}
130
-	return execGitCmd(ctx, workingDir, nil, nil, "notes", "--ref", notesRef, "add", "-m", string(b), rev)
129
+	return execGitCmd(ctx, workingDir, nil, "notes", "--ref", notesRef, "add", "-m", string(b), rev)
131 130
 }
132 131
 
133 132
 // NB return values (*Note, nil), (nil, error), (nil, nil)
134 133
 func getNote(ctx context.Context, workingDir, notesRef, rev string) (*Note, error) {
135 134
 	out := &bytes.Buffer{}
136
-	if err := execGitCmd(ctx, workingDir, nil, out, "notes", "--ref", notesRef, "show", rev); err != nil {
135
+	if err := execGitCmd(ctx, workingDir, out, "notes", "--ref", notesRef, "show", rev); err != nil {
137 136
 		if strings.Contains(strings.ToLower(err.Error()), "no note found for object") {
138 137
 			return nil, nil
139 138
 		}
@@ -151,7 +150,7 @@ func getNote(ctx context.Context, workingDir, notesRef, rev string) (*Note, erro
151 150
 // Return a map to make it easier to do "if in" type queries.
152 151
 func noteRevList(ctx context.Context, workingDir, notesRef string) (map[string]struct{}, error) {
153 152
 	out := &bytes.Buffer{}
154
-	if err := execGitCmd(ctx, workingDir, nil, out, "notes", "--ref", notesRef, "list"); err != nil {
153
+	if err := execGitCmd(ctx, workingDir, out, "notes", "--ref", notesRef, "list"); err != nil {
155 154
 		return nil, err
156 155
 	}
157 156
 	noteList := splitList(out.String())
@@ -168,7 +167,7 @@ func noteRevList(ctx context.Context, workingDir, notesRef string) (map[string]s
168 167
 // Get the commit hash for a reference
169 168
 func refRevision(ctx context.Context, path, ref string) (string, error) {
170 169
 	out := &bytes.Buffer{}
171
-	if err := execGitCmd(ctx, path, nil, out, "rev-list", "--max-count", "1", ref); err != nil {
170
+	if err := execGitCmd(ctx, path, out, "rev-list", "--max-count", "1", ref); err != nil {
172 171
 		return "", err
173 172
 	}
174 173
 	return strings.TrimSpace(out.String()), nil
@@ -176,7 +175,7 @@ func refRevision(ctx context.Context, path, ref string) (string, error) {
176 175
 
177 176
 func revlist(ctx context.Context, path, ref string) ([]string, error) {
178 177
 	out := &bytes.Buffer{}
179
-	if err := execGitCmd(ctx, path, nil, out, "rev-list", ref); err != nil {
178
+	if err := execGitCmd(ctx, path, out, "rev-list", ref); err != nil {
180 179
 		return nil, err
181 180
 	}
182 181
 	return splitList(out.String()), nil
@@ -191,13 +190,13 @@ func onelinelog(ctx context.Context, path, refspec, subdir string) ([]Commit, er
191 190
 	// because supplying an empty string to execGitCmd results in git complaining about
192 191
 	// >> ambiguous argument '' <<
193 192
 	if subdir != "" {
194
-		if err := execGitCmd(ctx, path, nil, out, "log", "--oneline", "--no-abbrev-commit", refspec, subdir); err != nil {
193
+		if err := execGitCmd(ctx, path, out, "log", "--oneline", "--no-abbrev-commit", refspec, subdir); err != nil {
195 194
 			return nil, err
196 195
 		}
197 196
 		return splitLog(out.String())
198 197
 	}
199 198
 
200
-	if err := execGitCmd(ctx, path, nil, out, "log", "--oneline", "--no-abbrev-commit", refspec); err != nil {
199
+	if err := execGitCmd(ctx, path, out, "log", "--oneline", "--no-abbrev-commit", refspec); err != nil {
201 200
 		return nil, err
202 201
 	}
203 202
 
@@ -224,11 +223,11 @@ func splitList(s string) []string {
224 223
 }
225 224
 
226 225
 // Move the tag to the ref given and push that tag upstream
227
-func moveTagAndPush(ctx context.Context, path string, keyRing ssh.KeyRing, tag, ref, msg, upstream string) error {
228
-	if err := execGitCmd(ctx, path, nil, nil, "tag", "--force", "-a", "-m", msg, tag, ref); err != nil {
226
+func moveTagAndPush(ctx context.Context, path string, tag, ref, msg, upstream string) error {
227
+	if err := execGitCmd(ctx, path, nil, "tag", "--force", "-a", "-m", msg, tag, ref); err != nil {
229 228
 		return errors.Wrap(err, "moving tag "+tag)
230 229
 	}
231
-	if err := execGitCmd(ctx, path, keyRing, nil, "push", "--force", upstream, "tag", tag); err != nil {
230
+	if err := execGitCmd(ctx, path, nil, "push", "--force", upstream, "tag", tag); err != nil {
232 231
 		return errors.Wrap(err, "pushing tag to origin")
233 232
 	}
234 233
 	return nil
@@ -243,19 +242,19 @@ func changedFiles(ctx context.Context, path, subPath, ref string) ([]string, err
243 242
 	// This uses --diff-filter to only look at changes for file _in
244 243
 	// the working dir_; i.e, we do not report on things that no
245 244
 	// longer appear.
246
-	if err := execGitCmd(ctx, path, nil, out, "diff", "--name-only", "--diff-filter=ACMRT", ref, "--", subPath); err != nil {
245
+	if err := execGitCmd(ctx, path, out, "diff", "--name-only", "--diff-filter=ACMRT", ref, "--", subPath); err != nil {
247 246
 		return nil, err
248 247
 	}
249 248
 	return splitList(out.String()), nil
250 249
 }
251 250
 
252
-func execGitCmd(ctx context.Context, dir string, keyRing ssh.KeyRing, out io.Writer, args ...string) error {
251
+func execGitCmd(ctx context.Context, dir string, out io.Writer, args ...string) error {
253 252
 	c := exec.CommandContext(ctx, "git", args...)
254 253
 
255 254
 	if dir != "" {
256 255
 		c.Dir = dir
257 256
 	}
258
-	c.Env = env(keyRing)
257
+	c.Env = env()
259 258
 	c.Stdout = ioutil.Discard
260 259
 	if out != nil {
261 260
 		c.Stdout = out
@@ -278,19 +277,14 @@ func execGitCmd(ctx context.Context, dir string, keyRing ssh.KeyRing, out io.Wri
278 277
 	return err
279 278
 }
280 279
 
281
-func env(keyRing ssh.KeyRing) []string {
282
-	base := `GIT_SSH_COMMAND=ssh -o LogLevel=error`
283
-	if keyRing == nil {
284
-		return []string{base}
285
-	}
286
-	_, privateKeyPath := keyRing.KeyPair()
287
-	return []string{fmt.Sprintf("%s -i %q", base, privateKeyPath), "GIT_TERMINAL_PROMPT=0"}
280
+func env() []string {
281
+	return []string{"GIT_TERMINAL_PROMPT=0"}
288 282
 }
289 283
 
290 284
 // check returns true if there are changes locally.
291 285
 func check(ctx context.Context, workingDir, subdir string) bool {
292 286
 	// `--quiet` means "exit with 1 if there are changes"
293
-	return execGitCmd(ctx, workingDir, nil, nil, "diff", "--quiet", "--", subdir) != nil
287
+	return execGitCmd(ctx, workingDir, nil, "diff", "--quiet", "--", subdir) != nil
294 288
 }
295 289
 
296 290
 func findErrorMessage(output io.Reader) string {

+ 9
- 11
git/repo.go View File

@@ -11,7 +11,6 @@ import (
11 11
 	"time"
12 12
 
13 13
 	"github.com/weaveworks/flux"
14
-	"github.com/weaveworks/flux/ssh"
15 14
 )
16 15
 
17 16
 const (
@@ -26,7 +25,6 @@ var (
26 25
 // Repo represents a (remote) git repo.
27 26
 type Repo struct {
28 27
 	flux.GitRemoteConfig
29
-	KeyRing ssh.KeyRing
30 28
 }
31 29
 
32 30
 // Checkout is a local clone of the remote repo.
@@ -70,7 +68,7 @@ func (r Repo) Clone(ctx context.Context, c Config) (*Checkout, error) {
70 68
 		return nil, err
71 69
 	}
72 70
 
73
-	repoDir, err := clone(ctx, workingDir, r.KeyRing, r.URL, r.Branch)
71
+	repoDir, err := clone(ctx, workingDir, r.URL, r.Branch)
74 72
 	if err != nil {
75 73
 		return nil, CloningError(r.URL, err)
76 74
 	}
@@ -85,7 +83,7 @@ func (r Repo) Clone(ctx context.Context, c Config) (*Checkout, error) {
85 83
 	}
86 84
 
87 85
 	// this fetches and updates the local ref, so we'll see notes
88
-	if err := fetch(ctx, r.KeyRing, repoDir, r.URL, notesRef+":"+notesRef); err != nil {
86
+	if err := fetch(ctx, repoDir, r.URL, notesRef+":"+notesRef); err != nil {
89 87
 		return nil, err
90 88
 	}
91 89
 
@@ -108,7 +106,7 @@ func (c *Checkout) WorkingClone(ctx context.Context) (*Checkout, error) {
108 106
 		return nil, err
109 107
 	}
110 108
 
111
-	repoDir, err := clone(ctx, workingDir, nil, c.Dir, c.repo.Branch)
109
+	repoDir, err := clone(ctx, workingDir, c.Dir, c.repo.Branch)
112 110
 	if err != nil {
113 111
 		return nil, err
114 112
 	}
@@ -118,7 +116,7 @@ func (c *Checkout) WorkingClone(ctx context.Context) (*Checkout, error) {
118 116
 	}
119 117
 
120 118
 	// this fetches and updates the local ref, so we'll see notes
121
-	if err := fetch(ctx, nil, repoDir, c.Dir, c.realNotesRef+":"+c.realNotesRef); err != nil {
119
+	if err := fetch(ctx, repoDir, c.Dir, c.realNotesRef+":"+c.realNotesRef); err != nil {
122 120
 		return nil, err
123 121
 	}
124 122
 
@@ -148,7 +146,7 @@ func (c *Checkout) ManifestDir() string {
148 146
 func (c *Checkout) CheckOriginWritable(ctx context.Context) error {
149 147
 	c.Lock()
150 148
 	defer c.Unlock()
151
-	if err := checkPush(ctx, c.repo.KeyRing, c.Dir, c.repo.URL); err != nil {
149
+	if err := checkPush(ctx, c.Dir, c.repo.URL); err != nil {
152 150
 		return ErrUpstreamNotWritable(c.repo.URL, err)
153 151
 	}
154 152
 	return nil
@@ -184,7 +182,7 @@ func (c *Checkout) CommitAndPush(ctx context.Context, commitAction *CommitAction
184 182
 		return err
185 183
 	}
186 184
 
187
-	if err := push(ctx, c.repo.KeyRing, c.Dir, c.repo.URL, refs); err != nil {
185
+	if err := push(ctx, c.Dir, c.repo.URL, refs); err != nil {
188 186
 		return PushError(c.repo.URL, err)
189 187
 	}
190 188
 	return nil
@@ -201,7 +199,7 @@ func (c *Checkout) GetNote(ctx context.Context, rev string) (*Note, error) {
201 199
 func (c *Checkout) Pull(ctx context.Context) error {
202 200
 	c.Lock()
203 201
 	defer c.Unlock()
204
-	if err := pull(ctx, c.repo.KeyRing, c.Dir, c.repo.URL, c.repo.Branch); err != nil {
202
+	if err := pull(ctx, c.Dir, c.repo.URL, c.repo.Branch); err != nil {
205 203
 		return err
206 204
 	}
207 205
 	for _, ref := range []string{
@@ -211,7 +209,7 @@ func (c *Checkout) Pull(ctx context.Context) error {
211 209
 		// this fetches and updates the local ref, so we'll see the new
212 210
 		// notes; but it's possible that the upstream doesn't have this
213 211
 		// ref.
214
-		if err := fetch(ctx, c.repo.KeyRing, c.Dir, c.repo.URL, ref); err != nil {
212
+		if err := fetch(ctx, c.Dir, c.repo.URL, ref); err != nil {
215 213
 			return err
216 214
 		}
217 215
 	}
@@ -245,7 +243,7 @@ func (c *Checkout) CommitsBefore(ctx context.Context, ref string) ([]Commit, err
245 243
 func (c *Checkout) MoveTagAndPush(ctx context.Context, ref, msg string) error {
246 244
 	c.Lock()
247 245
 	defer c.Unlock()
248
-	return moveTagAndPush(ctx, c.Dir, c.repo.KeyRing, c.SyncTag, ref, msg, c.repo.URL)
246
+	return moveTagAndPush(ctx, c.Dir, c.SyncTag, ref, msg, c.repo.URL)
249 247
 }
250 248
 
251 249
 // ChangedFiles does a git diff listing changed files

+ 22
- 0
ssh/keygen.go View File

@@ -9,6 +9,7 @@ import (
9 9
 	"regexp"
10 10
 	"strconv"
11 11
 
12
+	sshconfig "github.com/kevinburke/ssh_config"
12 13
 	"github.com/spf13/pflag"
13 14
 )
14 15
 
@@ -114,6 +115,27 @@ func KeyGen(keyBits, keyType OptionalValue, tmpfsPath string) (privateKeyPath st
114 115
 	return privateKeyPath, privateKey, publicKey, nil
115 116
 }
116 117
 
118
+func WriteSSHConfig(privateKeyPath string) error {
119
+	star, err := sshconfig.NewPattern("*")
120
+	if err != nil {
121
+		return err
122
+	}
123
+	sshconf := &sshconfig.Config{
124
+		Hosts: []*sshconfig.Host{
125
+			&sshconfig.Host{
126
+				Patterns: []*sshconfig.Pattern{star},
127
+				Nodes: []sshconfig.Node{
128
+					&sshconfig.KV{Key: "StrictHostKeyChecking", Value: "yes"},
129
+					&sshconfig.KV{Key: "IdentityFile", Value: privateKeyPath},
130
+					&sshconfig.KV{Key: "LogLevel", Value: "error"},
131
+				},
132
+			},
133
+		},
134
+	}
135
+	println("Output SSH config ", sshconf.String())
136
+	return ioutil.WriteFile("/etc/ssh/ssh_config", []byte(sshconf.String()), 0644)
137
+}
138
+
117 139
 type Fingerprint struct {
118 140
 	Hash      string `json:"hash"`
119 141
 	Randomart string `json:"randomart"`

Loading…
Cancel
Save