55"crypto/rand"
66"encoding/base64"
77"errors"
8- "log"
98gohttp"net/http"
109"path"
1110"regexp"
@@ -15,6 +14,7 @@ import (
1514"github.com/gaia-pipeline/gaia"
1615"github.com/gaia-pipeline/gaia/services"
1716"github.com/google/go-github/github"
17+ gossh"golang.org/x/crypto/ssh"
1818"golang.org/x/oauth2"
1919git"gopkg.in/src-d/go-git.v4"
2020"gopkg.in/src-d/go-git.v4/plumbing"
@@ -32,14 +32,19 @@ const (
3232// without actually cloning the repo. This is great
3333// for looking if we have access to this repo.
3434func GitLSRemote (repo * gaia.GitRepo )error {
35+ // Validate provided git url
36+ if strings .Contains (repo .URL ,"@" ) {
37+ return errors .New ("git url should not include username and/or password" )
38+ }
39+
3540// Create new endpoint
3641ep ,err := transport .NewEndpoint (repo .URL )
3742if err != nil {
3843return err
3944}
4045
4146// Attach credentials if provided
42- auth ,err := getAuthInfo (repo )
47+ auth ,err := getAuthInfo (repo , nil )
4348if err != nil {
4449return err
4550}
@@ -53,7 +58,19 @@ func GitLSRemote(repo *gaia.GitRepo) error {
5358// Open new session
5459s ,err := cl .NewUploadPackSession (ep ,auth )
5560if err != nil {
56- return err
61+ if strings .Contains (err .Error (),"knownhosts: key is unknown" ) {
62+ gaia .Cfg .Logger .Warn ("Warning: Unknown host key." ,"error" ,err .Error (),"URL" ,repo .URL )
63+ auth ,err := getAuthInfo (repo ,gossh .InsecureIgnoreHostKey ())
64+ if err != nil {
65+ return err
66+ }
67+ s ,err = cl .NewUploadPackSession (ep ,auth )
68+ if err != nil {
69+ return err
70+ }
71+ }else {
72+ return err
73+ }
5774}
5875defer s .Close ()
5976
@@ -79,7 +96,6 @@ func GitLSRemote(repo *gaia.GitRepo) error {
7996// it by pulling in new code if it's available.
8097func UpdateRepository (pipe * gaia.Pipeline )error {
8198r ,err := git .PlainOpen (pipe .Repo .LocalDest )
82- log .Println (pipe .Repo .LocalDest )
8399if err != nil {
84100// We don't stop gaia working because of an automated update failed.
85101// So we just move on.
@@ -88,23 +104,37 @@ func UpdateRepository(pipe *gaia.Pipeline) error {
88104}
89105gaia .Cfg .Logger .Debug ("checking pipeline: " ,"message" ,pipe .Name )
90106gaia .Cfg .Logger .Debug ("selected branch: " ,"message" ,pipe .Repo .SelectedBranch )
91- auth ,err := getAuthInfo (& pipe .Repo )
107+ auth ,err := getAuthInfo (& pipe .Repo , nil )
92108if err != nil {
93109// It's also an error if the repo is already up to date so we just move on.
94110gaia .Cfg .Logger .Error ("error getting auth info while doing a pull request: " ,"error" ,err .Error ())
95111return err
96112}
97113tree ,_ := r .Worktree ()
98- err = tree . Pull ( & git.PullOptions {
114+ o := & git.PullOptions {
99115ReferenceName :plumbing .ReferenceName (pipe .Repo .SelectedBranch ),
100116SingleBranch :true ,
101117RemoteName :"origin" ,
102118Auth :auth ,
103- })
119+ }
120+ err = tree .Pull (o )
104121if err != nil {
105- // It's also an error if the repo is already up to date so we just move on.
106- gaia .Cfg .Logger .Error ("error while doing a pull request: " ,"error" ,err .Error ())
107- return err
122+ if strings .Contains (err .Error (),"knownhosts: key is unknown" ) {
123+ gaia .Cfg .Logger .Warn ("Warning: Unknown host key." ,"error" ,err .Error (),"host" ,"URL" ,pipe .Repo .URL )
124+ auth ,err = getAuthInfo (& pipe .Repo ,gossh .InsecureIgnoreHostKey ())
125+ if err != nil {
126+ return err
127+ }
128+ o .Auth = auth
129+ err = tree .Pull (o )
130+ if err != nil {
131+ return err
132+ }
133+ }else {
134+ // It's also an error if the repo is already up to date so we just move on.
135+ gaia .Cfg .Logger .Error ("error while doing a pull request: " ,"error" ,err .Error ())
136+ return err
137+ }
108138}
109139
110140gaia .Cfg .Logger .Debug ("updating pipeline: " ,"message" ,pipe .Name )
@@ -121,21 +151,35 @@ func UpdateRepository(pipe *gaia.Pipeline) error {
121151// The destination will be attached to the given repo obj.
122152func gitCloneRepo (repo * gaia.GitRepo )error {
123153// Check if credentials were provided
124- auth ,err := getAuthInfo (repo )
154+ auth ,err := getAuthInfo (repo , nil )
125155if err != nil {
126156return err
127157}
128-
129- // Clone repo
130- _ ,err = git .PlainClone (repo .LocalDest ,false ,& git.CloneOptions {
158+ o := & git.CloneOptions {
131159Auth :auth ,
132160URL :repo .URL ,
133161RecurseSubmodules :git .DefaultSubmoduleRecursionDepth ,
134162SingleBranch :true ,
135163ReferenceName :plumbing .ReferenceName (repo .SelectedBranch ),
136- })
164+ }
165+ // Clone repo
166+ _ ,err = git .PlainClone (repo .LocalDest ,false ,o )
137167if err != nil {
138- return err
168+ if strings .Contains (err .Error (),"knownhosts: key is unknown" ) {
169+ gaia .Cfg .Logger .Warn ("Warning: Unknown host key." ,"error" ,err .Error (),"URL" ,repo .URL )
170+ auth ,err = getAuthInfo (repo ,gossh .InsecureIgnoreHostKey ())
171+ if err != nil {
172+ return err
173+ }
174+ o .Auth = auth
175+ // Clone repo again with no host key verification.
176+ _ ,err = git .PlainClone (repo .LocalDest ,false ,o )
177+ if err != nil {
178+ return err
179+ }
180+ }else {
181+ return err
182+ }
139183}
140184
141185return nil
@@ -255,7 +299,7 @@ func generateWebhookSecret() string {
255299return strings .TrimSuffix (based ,"==" )
256300}
257301
258- func getAuthInfo (repo * gaia.GitRepo ) (transport.AuthMethod ,error ) {
302+ func getAuthInfo (repo * gaia.GitRepo , callBack gossh. HostKeyCallback ) (transport.AuthMethod ,error ) {
259303var auth transport.AuthMethod
260304if repo .Username != "" && repo .Password != "" {
261305// Basic auth provided
@@ -269,6 +313,14 @@ func getAuthInfo(repo *gaia.GitRepo) (transport.AuthMethod, error) {
269313if err != nil {
270314return nil ,err
271315}
316+
317+ if callBack == nil {
318+ callBack ,err = ssh .NewKnownHostsCallback ()
319+ if err != nil {
320+ return nil ,err
321+ }
322+ }
323+ auth .(* ssh.PublicKeys ).HostKeyCallback = callBack
272324}
273325return auth ,nil
274326}