Verified Commit 0107a271 authored by Steve Azzopardi's avatar Steve Azzopardi
Browse files

Initial commit

parents
Copyright 2019-present Steve Azzopardi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
# tlsctl
A set of command line tools for to debug TLS certificates.
\ No newline at end of file
module gitlab.com/steveazz/tlsctl
go 1.13
require (
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa // indirect
github.com/sirupsen/logrus v1.4.2
github.com/urfave/cli v1.22.1
github.com/zakjan/cert-chain-resolver v0.0.0-20180703112424-6076e1ded272 // indirect
gitlab.com/gitlab-org/gitlab-runner v12.4.0+incompatible
)
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/zakjan/cert-chain-resolver v0.0.0-20180703112424-6076e1ded272 h1:scDk3LAM8x+NPuywVGC0q0/G+5Ed8M0+YXecz4XnWRM=
github.com/zakjan/cert-chain-resolver v0.0.0-20180703112424-6076e1ded272/go.mod h1:KNkcm66cr4ilOiEcjydK+tc2ShPUhqmuoXCljXUBPu8=
gitlab.com/gitlab-org/gitlab-runner v12.4.0+incompatible h1:2ztFSrCeDo+JvJxLubQ30afgSkJxM8Yg+RUH9rzRqF4=
gitlab.com/gitlab-org/gitlab-runner v12.4.0+incompatible/go.mod h1:M3GpuNDPpYOe9wMdFU1i3ev0BeKwqtRnvbf7niHoIHI=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
package main
import (
"os"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
func main() {
app := cli.NewApp()
app.Name = "tlsctl"
app.Usage = "Set of commands to debug TLS certificates for GitLab Runner."
app.Description = "Set of commands to debug TLS certificates for GitLab Runner."
app.Commands = []cli.Command{
makeSaveCMD(),
}
err := app.Run(os.Args)
if err != nil {
logrus.WithError(err).Fatal("Failed to run command")
}
}
package main
import (
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"gitlab.com/gitlab-org/gitlab-runner/helpers/tls/ca_chain"
)
var outDir = "/tmp/tlsctl"
func makeSaveCMD() cli.Command {
return cli.Command{
Name: "save",
Usage: "Use GitLab Runner TLS verification and save the chain in a file",
Flags: []cli.Flag{
cli.StringFlag{Name: "url"},
},
Action: saveAction,
}
}
func saveAction(c *cli.Context) error {
URL := c.String("url")
if URL == "" {
return errors.New("--url not defined")
}
response, err := http.Head(URL)
if err != nil {
return fmt.Errorf("sending request for TLS: %w", err)
}
if response.TLS == nil {
return errors.New("no TLS response found")
}
b := ca_chain.NewBuilder()
err = b.FetchCertificatesFromTLSConnectionState(response.TLS)
if err != nil {
return fmt.Errorf("fetching certificates from TLS: %w", err)
}
chain := []byte(b.String())
err = saveCAChain(chain)
if err != nil {
return fmt.Errorf("saving chain to file: %v", err)
}
for {
var block *pem.Block
block, chain = pem.Decode(chain)
err = savePemBlock(block)
if err != nil {
return fmt.Errorf("saving pem block to file: %w", err)
}
if chain == nil || len(chain) < 1 {
break
}
}
return nil
}
func savePemBlock(block *pem.Block) error {
err := mkdirIfNotExists(outDir)
if err != nil {
return fmt.Errorf("creating directory: %w", err)
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return fmt.Errorf("parsing certificate: %w", err)
}
filePath := fmt.Sprintf("%s/%s", outDir, cert.SerialNumber)
f, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("creating file for cert %s: %w", cert.SerialNumber, err)
}
err = pem.Encode(f, block)
if err != nil {
return fmt.Errorf("writing cert to file %s: %w", f.Name(), err)
}
logrus.WithFields(logrus.Fields{
"serial": cert.SerialNumber,
"subject": cert.Subject,
"path": filePath,
}).Info("Save cert file")
return nil
}
func saveCAChain(chain []byte) error {
err := mkdirIfNotExists(outDir)
if err != nil {
return err
}
path := fmt.Sprintf("%s/CAChain.crt", outDir)
logrus.WithField("path", path).Info("Save CAChain")
return ioutil.WriteFile("/tmp/tlsctl/CAChain.crt", chain, 0600)
}
func mkdirIfNotExists(path string) error {
if _, err := os.Stat(path); os.IsNotExist(err) {
err := os.MkdirAll(path, 0700)
if err != nil {
return fmt.Errorf("creating directory %q: %w", path, err)
}
}
return nil
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment