gitlab.com/jfprevost/gitlab-runner-notlscheck@v11.11.4+incompatible/common/support.go (about) 1 package common 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "crypto/rsa" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "encoding/pem" 10 "fmt" 11 "math/big" 12 "net/http" 13 "os" 14 "path" 15 "runtime" 16 "strings" 17 "time" 18 19 "github.com/tevino/abool" 20 ) 21 22 const ( 23 repoRemoteURL = "https://gitlab.com/gitlab-org/ci-cd/tests/gitlab-test.git" 24 25 repoRefType = RefTypeBranch 26 27 repoSHA = "91956efe32fb7bef54f378d90c9bd74c19025872" 28 repoBeforeSHA = "ca50079dac5293292f83a4d454922ba8db44e7a3" 29 repoRefName = "master" 30 31 repoLFSSHA = "2371dd05e426fca09b0d2ec5d9ed757559035e2f" 32 repoLFSBeforeSHA = "91956efe32fb7bef54f378d90c9bd74c19025872" 33 repoLFSRefName = "add-lfs-object" 34 35 repoSubmoduleLFSSHA = "d0cb7ff49b5c4fcf159e860fd6b30ef40731c435" 36 repoSubmoduleLFSBeforeSHA = "dcbc4f0c93cb1731eeac4e3a70a55a991838e137" 37 repoSubmoduleLFSRefName = "add-lfs-submodule" 38 39 FilesLFSFile1LFSsize = int64(2097152) 40 ) 41 42 var ( 43 gitLabComChain string 44 gitLabComChainFetched *abool.AtomicBool 45 ) 46 47 func init() { 48 gitLabComChainFetched = abool.New() 49 } 50 51 func GetGitInfo(url string) GitInfo { 52 return GitInfo{ 53 RepoURL: url, 54 Sha: repoSHA, 55 BeforeSha: repoBeforeSHA, 56 Ref: repoRefName, 57 RefType: repoRefType, 58 Refspecs: []string{"+refs/heads/*:refs/origin/heads/*", "+refs/tags/*:refs/tags/*"}, 59 } 60 } 61 62 func GetLFSGitInfo(url string) GitInfo { 63 return GitInfo{ 64 RepoURL: url, 65 Sha: repoLFSSHA, 66 BeforeSha: repoLFSBeforeSHA, 67 Ref: repoLFSRefName, 68 RefType: repoRefType, 69 Refspecs: []string{"+refs/heads/*:refs/origin/heads/*", "+refs/tags/*:refs/tags/*"}, 70 } 71 } 72 73 func GetSubmoduleLFSGitInfo(url string) GitInfo { 74 return GitInfo{ 75 RepoURL: url, 76 Sha: repoSubmoduleLFSSHA, 77 BeforeSha: repoSubmoduleLFSBeforeSHA, 78 Ref: repoSubmoduleLFSRefName, 79 RefType: repoRefType, 80 Refspecs: []string{"+refs/heads/*:refs/origin/heads/*", "+refs/tags/*:refs/tags/*"}, 81 } 82 } 83 84 func GetSuccessfulBuild() (JobResponse, error) { 85 return GetLocalBuildResponse("echo Hello World") 86 } 87 88 func GetRemoteSuccessfulBuild() (JobResponse, error) { 89 return GetRemoteBuildResponse("echo Hello World") 90 } 91 92 func GetRemoteSuccessfulLFSBuild() (JobResponse, error) { 93 response, err := GetRemoteBuildResponse("echo Hello World") 94 response.GitInfo = GetLFSGitInfo(repoRemoteURL) 95 96 return response, err 97 } 98 99 func GetRemoteSuccessfulBuildWithAfterScript() (JobResponse, error) { 100 jobResponse, err := GetRemoteBuildResponse("echo Hello World") 101 jobResponse.Steps = append(jobResponse.Steps, 102 Step{ 103 Name: StepNameAfterScript, 104 Script: []string{"echo Hello World"}, 105 When: StepWhenAlways, 106 }, 107 ) 108 return jobResponse, err 109 } 110 111 func GetRemoteSuccessfulBuildWithDumpedVariables() (JobResponse, error) { 112 variableName := "test_dump" 113 variableValue := "test" 114 115 response, err := GetRemoteBuildResponse( 116 fmt.Sprintf("[[ \"${%s}\" != \"\" ]]", variableName), 117 fmt.Sprintf("[[ $(cat $%s) == \"%s\" ]]", variableName, variableValue), 118 ) 119 120 if err != nil { 121 return JobResponse{}, err 122 } 123 124 dumpedVariable := JobVariable{ 125 Key: variableName, Value: variableValue, 126 Internal: true, Public: true, File: true, 127 } 128 response.Variables = append(response.Variables, dumpedVariable) 129 130 return response, nil 131 } 132 133 func GetFailedBuild() (JobResponse, error) { 134 return GetLocalBuildResponse("exit 1") 135 } 136 137 func GetRemoteFailedBuild() (JobResponse, error) { 138 return GetRemoteBuildResponse("exit 1") 139 } 140 141 func GetLongRunningBuild() (JobResponse, error) { 142 return GetLocalBuildResponse("sleep 3600") 143 } 144 145 func GetRemoteLongRunningBuild() (JobResponse, error) { 146 return GetRemoteBuildResponse("sleep 3600") 147 } 148 149 func GetMultilineBashBuild() (JobResponse, error) { 150 return GetRemoteBuildResponse(`if true; then 151 bash \ 152 --login \ 153 -c 'echo Hello World' 154 fi 155 `) 156 } 157 158 func GetRemoteBrokenTLSBuild() (JobResponse, error) { 159 invalidCert, err := buildSnakeOilCert() 160 if err != nil { 161 return JobResponse{}, err 162 } 163 164 return getRemoteCustomTLSBuild(invalidCert) 165 } 166 167 func GetRemoteGitLabComTLSBuild() (JobResponse, error) { 168 cert, err := getGitLabComTLSChain() 169 if err != nil { 170 return JobResponse{}, err 171 } 172 173 return getRemoteCustomTLSBuild(cert) 174 } 175 176 func getRemoteCustomTLSBuild(chain string) (JobResponse, error) { 177 job, err := GetRemoteBuildResponse("echo Hello World") 178 if err != nil { 179 return JobResponse{}, err 180 } 181 182 job.TLSCAChain = chain 183 job.Variables = append(job.Variables, 184 JobVariable{Key: "GIT_STRATEGY", Value: "clone"}, 185 JobVariable{Key: "GIT_SUBMODULE_STRATEGY", Value: "normal"}) 186 187 return job, nil 188 } 189 190 func getBuildResponse(repoURL string, commands []string) JobResponse { 191 return JobResponse{ 192 GitInfo: GetGitInfo(repoURL), 193 Steps: Steps{ 194 Step{ 195 Name: StepNameScript, 196 Script: commands, 197 When: StepWhenAlways, 198 AllowFailure: false, 199 }, 200 }, 201 } 202 } 203 204 func GetRemoteBuildResponse(commands ...string) (JobResponse, error) { 205 return getBuildResponse(repoRemoteURL, commands), nil 206 } 207 208 func GetLocalBuildResponse(commands ...string) (JobResponse, error) { 209 localRepoURL, err := getLocalRepoURL() 210 if err != nil { 211 return JobResponse{}, err 212 } 213 214 return getBuildResponse(localRepoURL, commands), nil 215 } 216 217 func getLocalRepoURL() (string, error) { 218 _, filename, _, _ := runtime.Caller(0) 219 220 directory := path.Dir(filename) 221 if strings.Contains(directory, "_test/_obj_test") { 222 pwd, err := os.Getwd() 223 if err != nil { 224 return "", err 225 } 226 directory = pwd 227 } 228 229 localRepoURL := path.Clean(directory + "/../tmp/gitlab-test/.git") 230 231 _, err := os.Stat(localRepoURL) 232 if err != nil { 233 return "", err 234 } 235 236 return localRepoURL, nil 237 } 238 239 func buildSnakeOilCert() (string, error) { 240 priv, err := rsa.GenerateKey(rand.Reader, 1024) 241 if err != nil { 242 return "", err 243 } 244 245 notBefore := time.Now() 246 notAfter := notBefore.Add(time.Hour) 247 248 template := x509.Certificate{ 249 SerialNumber: big.NewInt(1), 250 Subject: pkix.Name{ 251 Organization: []string{"Snake Oil Co"}, 252 }, 253 NotBefore: notBefore, 254 NotAfter: notAfter, 255 256 IsCA: true, 257 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, 258 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 259 BasicConstraintsValid: true, 260 } 261 262 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) 263 if err != nil { 264 return "", err 265 } 266 267 certificate := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 268 269 return string(certificate), nil 270 } 271 272 func getGitLabComTLSChain() (string, error) { 273 if gitLabComChainFetched.IsSet() { 274 return gitLabComChain, nil 275 } 276 277 resp, err := http.Head("https://gitlab.com/users/sign_in") 278 if err != nil { 279 return "", err 280 } 281 282 var buff bytes.Buffer 283 for _, certs := range resp.TLS.VerifiedChains { 284 for _, cert := range certs { 285 err = pem.Encode(&buff, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) 286 if err != nil { 287 return "", err 288 } 289 } 290 } 291 292 gitLabComChain = buff.String() 293 gitLabComChainFetched.Set() 294 295 return gitLabComChain, nil 296 }