guess cert format
This commit is contained in:
parent
95fbe59fd2
commit
8060fffba3
|
|
@ -295,16 +295,16 @@ func main() {
|
||||||
// default behavior is to use tls
|
// default behavior is to use tls
|
||||||
usetls := !*plaintext && !*usealts
|
usetls := !*plaintext && !*usealts
|
||||||
|
|
||||||
// converto to CertificateFileType
|
//// converto to CertificateFileType
|
||||||
if len(*certTypeString) == 0 {
|
//if len(*certTypeString) == 0 {
|
||||||
certType = grpcurl.CertTypePEM // default PEM
|
// certType = grpcurl.CertTypePEM // default PEM
|
||||||
} else if strings.EqualFold(*certTypeString, "PEM") {
|
//} else if strings.EqualFold(*certTypeString, "PEM") {
|
||||||
certType = grpcurl.CertTypePEM
|
// certType = grpcurl.CertTypePEM
|
||||||
} else if strings.EqualFold(*certTypeString, "P12") {
|
//} else if strings.EqualFold(*certTypeString, "P12") {
|
||||||
certType = grpcurl.CertTypeP12
|
// certType = grpcurl.CertTypeP12
|
||||||
} else {
|
//} else {
|
||||||
fail(nil, "The -cert-type argument must be PEM or P12.")
|
// fail(nil, "The -cert-type argument must be PEM or P12.")
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Do extra validation on arguments and figure out what user asked us to do.
|
// Do extra validation on arguments and figure out what user asked us to do.
|
||||||
if *connectTimeout < 0 {
|
if *connectTimeout < 0 {
|
||||||
|
|
@ -332,21 +332,21 @@ func main() {
|
||||||
fail(nil, "The -key argument can only be used with TLS.")
|
fail(nil, "The -key argument can only be used with TLS.")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch certType {
|
//switch certType {
|
||||||
case grpcurl.CertTypePEM:
|
//case grpcurl.CertTypePEM:
|
||||||
if (*key == "") != (*cert == "") {
|
// if (*key == "") != (*cert == "") {
|
||||||
fail(nil, "The -cert and -key arguments must be used together and both be present when -cert-type is PEM.")
|
// fail(nil, "The -cert and -key arguments must be used together and both be present when -cert-type is PEM.")
|
||||||
}
|
// }
|
||||||
case grpcurl.CertTypeP12:
|
//case grpcurl.CertTypeP12:
|
||||||
if *key != "" {
|
// if *key != "" {
|
||||||
fail(nil, "The -key arguments must not be used when -cert-type is P12.")
|
// fail(nil, "The -key arguments must not be used when -cert-type is P12.")
|
||||||
}
|
// }
|
||||||
if *cert == "" {
|
// if *cert == "" {
|
||||||
fail(nil, "The -cert arguments must be used when -cert-type is P12.")
|
// fail(nil, "The -cert arguments must be used when -cert-type is P12.")
|
||||||
}
|
// }
|
||||||
default:
|
//default:
|
||||||
fail(nil, "Not support cert type %v.", certType)
|
// fail(nil, "Not support cert type %v.", certType)
|
||||||
}
|
//}
|
||||||
|
|
||||||
if *altsHandshakerServiceAddress != "" && !*usealts {
|
if *altsHandshakerServiceAddress != "" && !*usealts {
|
||||||
fail(nil, "The -alts-handshaker-service argument must be used with the -alts argument.")
|
fail(nil, "The -alts-handshaker-service argument must be used with the -alts argument.")
|
||||||
|
|
|
||||||
18
go.mod
18
go.mod
|
|
@ -5,6 +5,7 @@ go 1.18
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.5.3
|
github.com/golang/protobuf v1.5.3
|
||||||
github.com/jhump/protoreflect v1.15.3
|
github.com/jhump/protoreflect v1.15.3
|
||||||
|
github.com/square/certigo v1.16.0
|
||||||
golang.org/x/crypto v0.14.0
|
golang.org/x/crypto v0.14.0
|
||||||
google.golang.org/grpc v1.57.0
|
google.golang.org/grpc v1.57.0
|
||||||
google.golang.org/protobuf v1.31.0
|
google.golang.org/protobuf v1.31.0
|
||||||
|
|
@ -13,6 +14,11 @@ require (
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute v1.19.1 // indirect
|
cloud.google.com/go/compute v1.19.1 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
|
github.com/Masterminds/goutils v1.1.0 // indirect
|
||||||
|
github.com/Masterminds/semver v1.4.2 // indirect
|
||||||
|
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
|
||||||
github.com/bufbuild/protocompile v0.6.0 // indirect
|
github.com/bufbuild/protocompile v0.6.0 // indirect
|
||||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
|
@ -20,13 +26,25 @@ require (
|
||||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect
|
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect
|
||||||
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f // indirect
|
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f // indirect
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect
|
github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect
|
||||||
|
github.com/fatih/color v1.13.0 // indirect
|
||||||
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
|
github.com/huandu/xstrings v1.2.0 // indirect
|
||||||
|
github.com/imdario/mergo v0.3.6 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||||
|
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8 // indirect
|
||||||
golang.org/x/net v0.17.0 // indirect
|
golang.org/x/net v0.17.0 // indirect
|
||||||
golang.org/x/oauth2 v0.7.0 // indirect
|
golang.org/x/oauth2 v0.7.0 // indirect
|
||||||
golang.org/x/sync v0.3.0 // indirect
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
golang.org/x/sys v0.13.0 // indirect
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
|
golang.org/x/term v0.13.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
golang.org/x/text v0.13.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 // indirect
|
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
|
||||||
|
gopkg.in/asn1-ber.v1 v1.0.0-20170511165959-379148ca0225 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
60
go.sum
60
go.sum
|
|
@ -4,6 +4,16 @@ cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IK
|
||||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
|
||||||
|
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
|
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
|
||||||
|
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
|
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
|
||||||
|
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY=
|
github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY=
|
||||||
github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE=
|
github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
|
@ -17,13 +27,17 @@ github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XP
|
||||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
||||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=
|
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=
|
||||||
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
|
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=
|
github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
|
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
|
||||||
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
|
@ -35,13 +49,39 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
|
||||||
|
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
|
||||||
|
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||||
|
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=
|
github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=
|
||||||
github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k=
|
github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k=
|
||||||
|
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||||
|
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||||
|
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
|
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8 h1:BhQQWYKJwXPtAhm12d4gQU4LKS9Yov22yOrDc2QA7ho=
|
||||||
|
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8/go.mod h1:ntWhh7pzdiiRKBMxUB5iG+Q2gmZBxGxpX1KyK6N8kX8=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/square/certigo v1.16.0 h1:8g9UgWssUcOMzeFJF0nSMGjmDVXBk6UTZNOMArxcrxM=
|
||||||
|
github.com/square/certigo v1.16.0/go.mod h1:v9HqynkvfNbHR0aluXlxutyGsZbUpiNACLkYpHyxRlU=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
|
@ -53,6 +93,7 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
|
@ -65,10 +106,21 @@ golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||||
|
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
@ -98,6 +150,14 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
|
gopkg.in/asn1-ber.v1 v1.0.0-20170511165959-379148ca0225 h1:JBwmEvLfCqgPcIq8MjVMQxsF3LVL4XG/HH0qiG0+IFY=
|
||||||
|
gopkg.in/asn1-ber.v1 v1.0.0-20170511165959-379148ca0225/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
||||||
47
grpcurl.go
47
grpcurl.go
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fullstorydev/grpcurl/internal/certigo/lib"
|
||||||
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
|
"github.com/golang/protobuf/proto" //lint:ignore SA1019 we have to import this because it appears in exported API
|
||||||
"github.com/jhump/protoreflect/desc"
|
"github.com/jhump/protoreflect/desc"
|
||||||
"github.com/jhump/protoreflect/desc/protoprint"
|
"github.com/jhump/protoreflect/desc/protoprint"
|
||||||
|
|
@ -549,16 +550,29 @@ func ClientTLSConfigV2(insecureSkipVerify bool, cacertFile, clientCertFile, clie
|
||||||
|
|
||||||
if clientCertFile != "" {
|
if clientCertFile != "" {
|
||||||
// Load the client certificates from disk
|
// Load the client certificates from disk
|
||||||
var certificate tls.Certificate
|
clientCertFormat := ""
|
||||||
var err error
|
var pemBuf bytes.Buffer
|
||||||
switch clientCertType {
|
err := lib.ReadAsPEMEx(clientCertFile, clientCertFormat, clientPass, func(block *pem.Block, format string) error {
|
||||||
case CertTypeP12:
|
return pem.Encode(&pemBuf, block)
|
||||||
certificate, err = loadClientCertP12(clientCertFile, clientPass)
|
})
|
||||||
case CertTypePEM:
|
if err != nil {
|
||||||
certificate, err = tls.LoadX509KeyPair(clientCertFile, clientKeyFile)
|
return nil, fmt.Errorf("could not load client cert: %v", err)
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("not support client certificate type: %v", clientCertType)
|
|
||||||
}
|
}
|
||||||
|
pemBytes := pemBuf.Bytes()
|
||||||
|
pemKeyBytes := pemBytes
|
||||||
|
|
||||||
|
if clientKeyFile != "" {
|
||||||
|
var pemKeyBuf bytes.Buffer
|
||||||
|
err := lib.ReadAsPEMEx(clientKeyFile, clientCertFormat, clientPass, func(block *pem.Block, format string) error {
|
||||||
|
return pem.Encode(&pemKeyBuf, block)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not load client key: %v", err)
|
||||||
|
}
|
||||||
|
pemKeyBytes = pemKeyBuf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
certificate, err := tls.X509KeyPair(pemBytes, pemKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not load client key pair: %v", err)
|
return nil, fmt.Errorf("could not load client key pair: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -586,6 +600,21 @@ func ClientTLSConfigV2(insecureSkipVerify bool, cacertFile, clientCertFile, clie
|
||||||
return &tlsConf, nil
|
return &tlsConf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func inputFiles(fileNames []string) ([]*os.File, error) {
|
||||||
|
var files []*os.File
|
||||||
|
for _, filename := range fileNames {
|
||||||
|
if filename == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rawFile, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to open file: %s\n", err)
|
||||||
|
}
|
||||||
|
files = append(files, rawFile)
|
||||||
|
}
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
func loadClientCertP12(pfxFile, pfxPassword string) (tls.Certificate, error) {
|
func loadClientCertP12(pfxFile, pfxPassword string) (tls.Certificate, error) {
|
||||||
b, err := os.ReadFile(pfxFile)
|
b, err := os.ReadFile(pfxFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,425 @@
|
||||||
|
/*-
|
||||||
|
* Copyright 2016 Square Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/square/certigo/jceks"
|
||||||
|
"github.com/square/certigo/pkcs7"
|
||||||
|
"golang.org/x/crypto/pkcs12"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// nameHeader is the PEM header field for the friendly name/alias of the key in the key store.
|
||||||
|
nameHeader = "friendlyName"
|
||||||
|
|
||||||
|
// fileHeader is the origin file where the key came from (as in file on disk).
|
||||||
|
fileHeader = "originFile"
|
||||||
|
)
|
||||||
|
|
||||||
|
var fileExtToFormat = map[string]string{
|
||||||
|
".pem": "PEM",
|
||||||
|
".crt": "PEM",
|
||||||
|
".p7b": "PEM",
|
||||||
|
".p7c": "PEM",
|
||||||
|
".p12": "PKCS12",
|
||||||
|
".pfx": "PKCS12",
|
||||||
|
".jceks": "JCEKS",
|
||||||
|
".jks": "JCEKS", // Only partially supported
|
||||||
|
".der": "DER",
|
||||||
|
}
|
||||||
|
|
||||||
|
var badSignatureAlgorithms = [...]x509.SignatureAlgorithm{
|
||||||
|
x509.MD2WithRSA,
|
||||||
|
x509.MD5WithRSA,
|
||||||
|
x509.SHA1WithRSA,
|
||||||
|
x509.DSAWithSHA1,
|
||||||
|
x509.ECDSAWithSHA1,
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorFromErrors(errs []error) error {
|
||||||
|
if len(errs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(errs) == 1 {
|
||||||
|
return errs[0]
|
||||||
|
}
|
||||||
|
buffer := new(bytes.Buffer)
|
||||||
|
buffer.WriteString("encountered multiple errors:\n")
|
||||||
|
for _, err := range errs {
|
||||||
|
buffer.WriteString("* ")
|
||||||
|
buffer.WriteString(strings.TrimSuffix(err.Error(), "\n"))
|
||||||
|
buffer.WriteString("\n")
|
||||||
|
}
|
||||||
|
return errors.New(buffer.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAsPEMFromFiles will read PEM blocks from the given set of inputs. Input
|
||||||
|
// data may be in plain-text PEM files, DER-encoded certificates or PKCS7
|
||||||
|
// envelopes, or PKCS12/JCEKS keystores. All inputs will be converted to PEM
|
||||||
|
// blocks and passed to the callback.
|
||||||
|
func ReadAsPEMFromFiles(files []*os.File, format string, password func(string) string, callback func(*pem.Block, string) error) error {
|
||||||
|
var errs []error
|
||||||
|
for _, file := range files {
|
||||||
|
reader := bufio.NewReaderSize(file, 4)
|
||||||
|
format, err := formatForFile(reader, file.Name(), format)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to guess file type for file %s", file.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = readCertsFromStream(reader, file.Name(), format, password, callback)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorFromErrors(errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadAsPEMEx(filename string, format string, password string, callback func(*pem.Block, string) error) error {
|
||||||
|
rawFile, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to open file: %s\n", err)
|
||||||
|
}
|
||||||
|
defer rawFile.Close()
|
||||||
|
passwordFunc := func(promet string) string {
|
||||||
|
return password
|
||||||
|
}
|
||||||
|
return ReadAsPEM([]io.Reader{rawFile}, format, passwordFunc, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAsPEM will read PEM blocks from the given set of inputs. Input data may
|
||||||
|
// be in plain-text PEM files, DER-encoded certificates or PKCS7 envelopes, or
|
||||||
|
// PKCS12/JCEKS keystores. All inputs will be converted to PEM blocks and
|
||||||
|
// passed to the callback.
|
||||||
|
func ReadAsPEM(readers []io.Reader, format string, password func(string) string, callback func(*pem.Block, string) error) error {
|
||||||
|
errs := []error{}
|
||||||
|
for _, r := range readers {
|
||||||
|
reader := bufio.NewReaderSize(r, 4)
|
||||||
|
format, err := formatForFile(reader, "", format)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to guess format for input stream")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = readCertsFromStream(reader, "", format, password, callback)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorFromErrors(errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAsX509FromFiles will read X.509 certificates from the given set of
|
||||||
|
// inputs. Input data may be in plain-text PEM files, DER-encoded certificates
|
||||||
|
// or PKCS7 envelopes, or PKCS12/JCEKS keystores. All inputs will be converted
|
||||||
|
// to X.509 certificates (private keys are skipped) and passed to the callback.
|
||||||
|
func ReadAsX509FromFiles(files []*os.File, format string, password func(string) string, callback func(*x509.Certificate, string, error) error) error {
|
||||||
|
errs := []error{}
|
||||||
|
for _, file := range files {
|
||||||
|
reader := bufio.NewReaderSize(file, 4)
|
||||||
|
format, err := formatForFile(reader, file.Name(), format)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to guess file type for file %s, try adding --format flag", file.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = readCertsFromStream(reader, file.Name(), format, password, pemToX509(callback))
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorFromErrors(errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAsX509 will read X.509 certificates from the given set of inputs. Input
|
||||||
|
// data may be in plain-text PEM files, DER-encoded certificates or PKCS7
|
||||||
|
// envelopes, or PKCS12/JCEKS keystores. All inputs will be converted to X.509
|
||||||
|
// certificates (private keys are skipped) and passed to the callback.
|
||||||
|
func ReadAsX509(readers []io.Reader, format string, password func(string) string, callback func(*x509.Certificate, string, error) error) error {
|
||||||
|
errs := []error{}
|
||||||
|
for _, r := range readers {
|
||||||
|
reader := bufio.NewReaderSize(r, 4)
|
||||||
|
format, err := formatForFile(reader, "", format)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to guess format for input stream")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = readCertsFromStream(reader, "", format, password, pemToX509(callback))
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorFromErrors(errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pemToX509(callback func(*x509.Certificate, string, error) error) func(*pem.Block, string) error {
|
||||||
|
return func(block *pem.Block, format string) error {
|
||||||
|
switch block.Type {
|
||||||
|
case "CERTIFICATE":
|
||||||
|
cert, err := x509.ParseCertificate(block.Bytes)
|
||||||
|
return callback(cert, format, err)
|
||||||
|
case "PKCS7":
|
||||||
|
certs, err := pkcs7.ExtractCertificates(block.Bytes)
|
||||||
|
if err == nil {
|
||||||
|
for _, cert := range certs {
|
||||||
|
return callback(cert, format, nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return callback(nil, format, err)
|
||||||
|
}
|
||||||
|
case "CERTIFICATE REQUEST":
|
||||||
|
fmt.Println("warning: certificate requests are not supported")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadCertsFromStream(reader io.Reader, filename string, format string, password string, callback func(*pem.Block, string) error) error {
|
||||||
|
passwordFunc := func(promet string) string {
|
||||||
|
return password
|
||||||
|
}
|
||||||
|
return readCertsFromStream(reader, filename, format, passwordFunc, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// readCertsFromStream takes some input and converts it to PEM blocks.
|
||||||
|
func readCertsFromStream(reader io.Reader, filename string, format string, password func(string) string, callback func(*pem.Block, string) error) error {
|
||||||
|
headers := map[string]string{}
|
||||||
|
if filename != "" && filename != os.Stdin.Name() {
|
||||||
|
headers[fileHeader] = filename
|
||||||
|
}
|
||||||
|
|
||||||
|
format = strings.TrimSpace(format)
|
||||||
|
switch format {
|
||||||
|
case "PEM":
|
||||||
|
scanner := pemScanner(reader)
|
||||||
|
for scanner.Scan() {
|
||||||
|
block, _ := pem.Decode(scanner.Bytes())
|
||||||
|
block.Headers = mergeHeaders(block.Headers, headers)
|
||||||
|
err := callback(block, format)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case "DER":
|
||||||
|
data, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to read input: %s\n", err)
|
||||||
|
}
|
||||||
|
x509Certs, err0 := x509.ParseCertificates(data)
|
||||||
|
if err0 == nil {
|
||||||
|
for _, cert := range x509Certs {
|
||||||
|
err := callback(EncodeX509ToPEM(cert, headers), format)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p7bBlocks, err1 := pkcs7.ParseSignedData(data)
|
||||||
|
if err1 == nil {
|
||||||
|
for _, block := range p7bBlocks {
|
||||||
|
err := callback(pkcs7ToPem(block, headers), format)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unable to parse certificates from DER data\n* X.509 parser gave: %s\n* PKCS7 parser gave: %s\n", err0, err1)
|
||||||
|
case "PKCS12":
|
||||||
|
data, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to read input: %s\n", err)
|
||||||
|
}
|
||||||
|
blocks, err := pkcs12.ToPEM(data, password(""))
|
||||||
|
if err != nil || len(blocks) == 0 {
|
||||||
|
return fmt.Errorf("keystore appears to be empty or password was incorrect\n")
|
||||||
|
}
|
||||||
|
for _, block := range blocks {
|
||||||
|
block.Headers = mergeHeaders(block.Headers, headers)
|
||||||
|
err := callback(block, format)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case "JCEKS":
|
||||||
|
keyStore, err := jceks.LoadFromReader(reader, []byte(password("")))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to parse keystore: %s\n", err)
|
||||||
|
}
|
||||||
|
for _, alias := range keyStore.ListCerts() {
|
||||||
|
cert, _ := keyStore.GetCert(alias)
|
||||||
|
err := callback(EncodeX509ToPEM(cert, mergeHeaders(headers, map[string]string{nameHeader: alias})), format)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, alias := range keyStore.ListPrivateKeys() {
|
||||||
|
key, certs, err := keyStore.GetPrivateKeyAndCerts(alias, []byte(password(alias)))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to parse keystore: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mergedHeaders := mergeHeaders(headers, map[string]string{nameHeader: alias})
|
||||||
|
|
||||||
|
block, err := keyToPem(key, mergedHeaders)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("problem reading key: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := callback(block, format); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cert := range certs {
|
||||||
|
if err = callback(EncodeX509ToPEM(cert, mergedHeaders), format); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unknown file type '%s'\n", format)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeHeaders(baseHeaders, extraHeaders map[string]string) (headers map[string]string) {
|
||||||
|
headers = map[string]string{}
|
||||||
|
for k, v := range baseHeaders {
|
||||||
|
headers[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range extraHeaders {
|
||||||
|
headers[k] = v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeX509ToPEM converts an X.509 certificate into a PEM block for output.
|
||||||
|
func EncodeX509ToPEM(cert *x509.Certificate, headers map[string]string) *pem.Block {
|
||||||
|
return &pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: cert.Raw,
|
||||||
|
Headers: headers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a PKCS7 envelope into a PEM block for output.
|
||||||
|
func pkcs7ToPem(block *pkcs7.SignedDataEnvelope, headers map[string]string) *pem.Block {
|
||||||
|
return &pem.Block{
|
||||||
|
Type: "PKCS7",
|
||||||
|
Bytes: block.Raw,
|
||||||
|
Headers: headers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a key into one or more PEM blocks for output.
|
||||||
|
func keyToPem(key crypto.PrivateKey, headers map[string]string) (*pem.Block, error) {
|
||||||
|
switch k := key.(type) {
|
||||||
|
case *rsa.PrivateKey:
|
||||||
|
return &pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(k),
|
||||||
|
Headers: headers,
|
||||||
|
}, nil
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
raw, err := x509.MarshalECPrivateKey(k)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error marshaling key: %s\n", reflect.TypeOf(key))
|
||||||
|
}
|
||||||
|
return &pem.Block{
|
||||||
|
Type: "EC PRIVATE KEY",
|
||||||
|
Bytes: raw,
|
||||||
|
Headers: headers,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unknown key type: %s\n", reflect.TypeOf(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatForFile returns the file format (either from flags or
|
||||||
|
// based on file extension).
|
||||||
|
func formatForFile(file *bufio.Reader, filename, format string) (string, error) {
|
||||||
|
// First, honor --format flag we got from user
|
||||||
|
if format != "" {
|
||||||
|
return format, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second, attempt to guess based on extension
|
||||||
|
guess, ok := fileExtToFormat[strings.ToLower(filepath.Ext(filename))]
|
||||||
|
if ok {
|
||||||
|
return guess, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third, attempt to guess based on first 4 bytes of input
|
||||||
|
data, err := file.Peek(4)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("unable to read file: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heuristics for guessing -- best effort.
|
||||||
|
magic := binary.BigEndian.Uint32(data)
|
||||||
|
if magic == 0xCECECECE || magic == 0xFEEDFEED {
|
||||||
|
// JCEKS/JKS files always start with this prefix
|
||||||
|
return "JCEKS", nil
|
||||||
|
}
|
||||||
|
if magic == 0x2D2D2D2D || magic == 0x434f4e4e {
|
||||||
|
// Starts with '----' or 'CONN' (what s_client prints...)
|
||||||
|
return "PEM", nil
|
||||||
|
}
|
||||||
|
if magic&0xFFFF0000 == 0x30820000 {
|
||||||
|
// Looks like the input is DER-encoded, so it's either PKCS12 or X.509.
|
||||||
|
if magic&0x0000FF00 == 0x0300 {
|
||||||
|
// Probably X.509
|
||||||
|
return "DER", nil
|
||||||
|
}
|
||||||
|
return "PKCS12", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("unable to guess file format")
|
||||||
|
}
|
||||||
|
|
||||||
|
// pemScanner will return a bufio.Scanner that splits the input
|
||||||
|
// from the given reader into PEM blocks.
|
||||||
|
func pemScanner(reader io.Reader) *bufio.Scanner {
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
|
scanner.Split(func(data []byte, atEOF bool) (int, []byte, error) {
|
||||||
|
block, rest := pem.Decode(data)
|
||||||
|
if block != nil {
|
||||||
|
size := len(data) - len(rest)
|
||||||
|
return size, data[:size], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, nil, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return scanner
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue