mirror of
https://github.com/square/certigo.git
synced 2026-10-21 04:13:33 +00:00
Merge pull request #146 from square/cs/stuff2
Shell completion & URI names display
This commit is contained in:
+3
-1
@@ -1,2 +1,4 @@
|
||||
certigo
|
||||
certigo.exe
|
||||
certigo.exe
|
||||
man/
|
||||
shell/
|
||||
|
||||
@@ -17,3 +17,8 @@ go build -o bin/certigo ${REPO_PATH}
|
||||
# Generate man page
|
||||
mkdir -p man
|
||||
bin/certigo --help-man > man/certigo.1
|
||||
|
||||
# Generate completion scripts
|
||||
mkdir -p shell
|
||||
bin/certigo --completion-script-zsh > shell/certigo.completion.zsh
|
||||
bin/certigo --completion-script-bash > shell/certigo.completion.bash
|
||||
|
||||
Generated
+4
-2
@@ -1,5 +1,5 @@
|
||||
hash: f13313281515b6941a7f67c8dc051c6cd76314f3708fe93d1f701278856cfc1a
|
||||
updated: 2017-08-02T15:41:22.000418583-07:00
|
||||
hash: f7ccb11674e8a2d85c7cdc160a5dd7a3160b1280f9443879235148659939ffb5
|
||||
updated: 2017-08-07T15:26:47.237893811-07:00
|
||||
imports:
|
||||
- name: github.com/alecthomas/template
|
||||
version: a0175ee3bccc567396460bf5acd36800cb10c49c
|
||||
@@ -27,6 +27,8 @@ imports:
|
||||
repo: https://github.com/mattn/go-isatty
|
||||
- name: github.com/satori/go.uuid
|
||||
version: 879c5887cd475cd7864858769793b2ceb0d44feb
|
||||
- name: github.com/spiffe/go-spiffe
|
||||
version: 2a3d812e4ae000302a242cb42490ff395e9508de
|
||||
- name: golang.org/x/crypto
|
||||
version: 5bcd134fee4dd1475da17714aac19c0aa0142e2f
|
||||
subpackages:
|
||||
|
||||
@@ -12,3 +12,4 @@ import:
|
||||
version: ^1.2.0
|
||||
- package: github.com/Masterminds/sprig
|
||||
version: ^2.12.0
|
||||
- package: github.com/spiffe/go-spiffe
|
||||
|
||||
+10
-4
@@ -58,11 +58,14 @@ Key Usage:{{range .KeyUsage | keyUsage}}
|
||||
Extended Key Usage:{{range .ExtKeyUsage}}
|
||||
{{. | extKeyUsage}}{{end}}{{end}}
|
||||
{{- if .AltDNSNames}}
|
||||
Alternate DNS Names:
|
||||
DNS Names:
|
||||
{{wrapWith .Width "\n\t" (join ", " .AltDNSNames)}}{{end}}
|
||||
{{- if .AltIPAddresses}}
|
||||
Alternate IP Addresses:
|
||||
IP Addresses:
|
||||
{{wrapWith .Width "\n\t" (join ", " .AltIPAddresses)}}{{end}}
|
||||
{{- if .URINames}}
|
||||
URI Names:
|
||||
{{wrapWith .Width "\n\t" (join ", " .URINames)}}{{end}}
|
||||
{{- if .EmailAddresses}}
|
||||
Email Addresses:
|
||||
{{wrapWith .Width "\n\t" (join ", " .EmailAddresses)}}{{end}}
|
||||
@@ -80,11 +83,14 @@ Issuer: {{.Issuer.Name | printShortName }}
|
||||
Name Constraints{{if .PermittedDNSDomains.Critical}} (critical){{end}}: {{range .NameConstraints.PermittedDNSDomains}}
|
||||
{{.}}{{end}}{{end}}
|
||||
{{- if .AltDNSNames}}
|
||||
Alternate DNS Names:
|
||||
DNS Names:
|
||||
{{wrapWith .Width "\n\t" (join ", " .AltDNSNames)}}{{end}}
|
||||
{{- if .AltIPAddresses}}
|
||||
Alternate IP Addresses:
|
||||
IP Addresses:
|
||||
{{wrapWith .Width "\n\t" (join ", " .AltIPAddresses)}}{{end}}
|
||||
{{- if .URINames}}
|
||||
URI Names:
|
||||
{{wrapWith .Width "\n\t" (join ", " .URINames)}}{{end}}
|
||||
{{- if .EmailAddresses}}
|
||||
Email Addresses:
|
||||
{{wrapWith .Width "\n\t" (join ", " .EmailAddresses)}}{{end}}
|
||||
|
||||
@@ -32,6 +32,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spiffe/go-spiffe"
|
||||
)
|
||||
|
||||
var keyUsages = []x509.KeyUsage{
|
||||
@@ -189,6 +191,7 @@ type simpleCertificate struct {
|
||||
ExtKeyUsage []simpleExtKeyUsage `json:"extended_key_usage,omitempty"`
|
||||
AltDNSNames []string `json:"dns_names,omitempty"`
|
||||
AltIPAddresses []net.IP `json:"ip_addresses,omitempty"`
|
||||
URINames []string `json:"uri_names,omitempty"`
|
||||
EmailAddresses []string `json:"email_addresses,omitempty"`
|
||||
Warnings []string `json:"warnings,omitempty"`
|
||||
PEM string `json:"pem,omitempty"`
|
||||
@@ -231,6 +234,11 @@ func createSimpleCertificate(name string, cert *x509.Certificate) simpleCertific
|
||||
PEM: string(pem.EncodeToMemory(EncodeX509ToPEM(cert, nil))),
|
||||
}
|
||||
|
||||
uriNames, err := spiffe.GetURINamesFromCertificate(cert)
|
||||
if err != nil {
|
||||
out.URINames = uriNames
|
||||
}
|
||||
|
||||
if cert.BasicConstraintsValid {
|
||||
out.BasicConstraints = &basicConstraints{
|
||||
IsCA: cert.IsCA,
|
||||
|
||||
@@ -137,7 +137,7 @@ Dump a live cert chain (squareup-chain.crt)
|
||||
Extended Key Usage:
|
||||
\tServer Auth (esc)
|
||||
\tClient Auth (esc)
|
||||
Alternate DNS Names:
|
||||
DNS Names:
|
||||
\twww.squareup.com, squareup.com, (esc)
|
||||
\taccount.squareup.com, mkt.com, www.mkt.com, (esc)
|
||||
\tmarket.squareup.com, gosq.com, www.gosq.com, (esc)
|
||||
|
||||
@@ -31,8 +31,8 @@ Dump an example certificate (example-leaf.crt)
|
||||
Valid: 2016-06-10 22:14 UTC to 2023-04-15 22:14 UTC
|
||||
Subject: CN=example-leaf
|
||||
Issuer: CN=example-leaf
|
||||
Alternate DNS Names:
|
||||
DNS Names:
|
||||
\tlocalhost (esc)
|
||||
Alternate IP Addresses:
|
||||
IP Addresses:
|
||||
\t127.0.0.1, ::1 (esc)
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@ Dump an example certificate (example-leaf.crt)
|
||||
Extended Key Usage:
|
||||
\tClient Auth (esc)
|
||||
\tServer Auth (esc)
|
||||
Alternate DNS Names:
|
||||
DNS Names:
|
||||
\tlocalhost (esc)
|
||||
Alternate IP Addresses:
|
||||
IP Addresses:
|
||||
\t127.0.0.1, ::1 (esc)
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
Copyright 2017 Scytale, 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.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
test: vet
|
||||
go test
|
||||
|
||||
vet:
|
||||
go vet
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
# go-spiffe library
|
||||
|
||||
### Overview
|
||||
The go-spiffe library provides functionality to parse and verify SPIFFE identities encoded in X.509 certificates as described in the [SPIFFE Verifiable Identity Document (SVID) Document Specification](https://github.com/spiffe/svid/blob/master/SPECIFICATION.md).
|
||||
|
||||
#### func GetUrisInSubjectAltName
|
||||
|
||||
```go
|
||||
func GetUrisInSubjectAltName(certificateString string) (uris []string, err error)
|
||||
```
|
||||
Parses an X.509 certificate in PEM format and gets the URIs from the Subject Alternative Name extension.
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package spiffe
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var oidExtensionSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17}
|
||||
|
||||
func getURINamesFromSANExtension(sanExtension []byte) (uris []string, err error) {
|
||||
// RFC 5280, 4.2.1.6
|
||||
|
||||
// SubjectAltName ::= GeneralNames
|
||||
//
|
||||
// GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
|
||||
//
|
||||
// GeneralName ::= CHOICE {
|
||||
// otherName [0] OtherName,
|
||||
// rfc822Name [1] IA5String,
|
||||
// dNSName [2] IA5String,
|
||||
// x400Address [3] ORAddress,
|
||||
// directoryName [4] Name,
|
||||
// ediPartyName [5] EDIPartyName,
|
||||
// uniformResourceIdentifier [6] IA5String,
|
||||
// iPAddress [7] OCTET STRING,
|
||||
// registeredID [8] OBJECT IDENTIFIER }
|
||||
var seq asn1.RawValue
|
||||
var rest []byte
|
||||
if rest, err = asn1.Unmarshal(sanExtension, &seq); err != nil {
|
||||
return
|
||||
} else if len(rest) != 0 {
|
||||
err = errors.New("x509: trailing data after X.509 extension")
|
||||
return
|
||||
}
|
||||
if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 {
|
||||
err = asn1.StructuralError{Msg: "bad SAN sequence"}
|
||||
return
|
||||
}
|
||||
|
||||
rest = seq.Bytes
|
||||
for len(rest) > 0 {
|
||||
var v asn1.RawValue
|
||||
rest, err = asn1.Unmarshal(rest, &v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.Tag == 6 {
|
||||
uris = append(uris, string(v.Bytes))
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getExtensionsFromAsn1ObjectIdentifier(certificate *x509.Certificate, id asn1.ObjectIdentifier) []pkix.Extension {
|
||||
var extensions []pkix.Extension
|
||||
|
||||
for _, extension := range certificate.Extensions {
|
||||
if extension.Id.Equal(id) {
|
||||
extensions = append(extensions, extension)
|
||||
}
|
||||
}
|
||||
|
||||
return extensions
|
||||
}
|
||||
|
||||
// GetUrisInSubjectAltName takes a parsed X.509 certificate and gets the URIs from the SAN extension.
|
||||
func GetURINamesFromCertificate(cert *x509.Certificate) (uris []string, err error) {
|
||||
for _, ext := range getExtensionsFromAsn1ObjectIdentifier(cert, oidExtensionSubjectAltName) {
|
||||
uris, err = getURINamesFromSANExtension(ext.Value)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return uris, nil
|
||||
}
|
||||
|
||||
// GetUrisInSubjectAltNameEncoded parses a PEM-encoded X.509 certificate and gets the URIs from the SAN extension.
|
||||
func GetURINamesFromPEM(encodedCertificate string) (uris []string, err error) {
|
||||
block, _ := pem.Decode([]byte(encodedCertificate))
|
||||
if block == nil {
|
||||
return uris, errors.New("failed to decode certificate PEM")
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return uris, errors.New("failed to parse certificate: " + err.Error())
|
||||
}
|
||||
|
||||
return GetURINamesFromCertificate(cert)
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package spiffe
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func getCertificateFromFile(t *testing.T, certFilePath string) string {
|
||||
certificateString, err := ioutil.ReadFile(certFilePath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return string(certificateString)
|
||||
}
|
||||
|
||||
func TestGetURINamesFromPEM(t *testing.T) {
|
||||
certPEM := getCertificateFromFile(t, "testdata/leaf.cert.pem")
|
||||
|
||||
var golden = "spiffe://dev.acme.com/path/service"
|
||||
|
||||
uris, err := GetURINamesFromPEM(string(certPEM))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if len(uris) == 1 {
|
||||
if uris[0] != golden {
|
||||
t.Fatalf("Expected '%v' but got '%v'", golden, uris[0])
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Expected 1 URI but got '%v'", len(uris))
|
||||
}
|
||||
|
||||
certPEM = getCertificateFromFile(t, "testdata/intermediate.cert.pem")
|
||||
uris, err = GetURINamesFromPEM(string(certPEM))
|
||||
if err == nil {
|
||||
t.Fatal("Expected to fail")
|
||||
}
|
||||
|
||||
if len(uris) > 0 {
|
||||
t.Fatalf("Expected to have no URIs but got %v URIs", len(uris))
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFiDCCA3CgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwNzELMAkGA1UEBhMCVVMx
|
||||
FzAVBgNVBAoMDnRlc3QxLmFjbWUuY29tMQ8wDQYDVQQDDAZSb290Q0EwHhcNMTcw
|
||||
NzE5MTY1MDIwWhcNMTcxMDI3MTY1MDIwWjA/MQswCQYDVQQGEwJVUzEXMBUGA1UE
|
||||
CgwOdGVzdDEuYWNtZS5jb20xFzAVBgNVBAMMDkludGVybWVkaWFldENBMIICIjAN
|
||||
BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAph7QhbUKEjMWu2R/WXIc8RR0ymCL
|
||||
njJTm0D5duTe7V2hklLhCo1KnZAjvDiDX9r85UfEja5MYItHmFF4HOZjSG6nY3Yg
|
||||
Mm5hdJM7Jmv9NJR8DJInROabfRcaPdugs2UQ41jCEygIoWiZ9+yVlZ21MNW0yQdI
|
||||
JHUNndQfXpS7dBdKw6fUqzZgpdzo86mAapZDIPL7gXv6MW8JhbvQCm+bg7SRIJOD
|
||||
t/a1T0nHPNuwxdDWjGcmJEQRknffL8pheDlW9sMAd/4BtIeaWUEb3JjdDoaJ9SWU
|
||||
tCgGRZOMnmry8npJnssyoLUtIPuk8949REOUB15nT94EhTtb1BMdiuD8P8HOHWC6
|
||||
mcxpJCsKlCFmOQpES6WROqjckQJ0f/xPOdKAdI9W0Eg3TRtibV9XTfTvv8SPug9/
|
||||
6FnkdpwF5xlJ/XcuW8GtpHUZNQ0NyxjUh2rQRAbwdTMeCvhx5fPHpT2kc6PIlzLw
|
||||
h4Pt0Xvc1cNt2iJOVDqs75HvvUe4RYTfdqlK5385u/s2cxQrLuB4owJrTyrqc3yM
|
||||
L/0h5JXr9P+T+axrd5WQWz2ngiaimli2vxZTR++RfBnyCgQGTiY+9UUOYYgHh6hJ
|
||||
CGUPY77DsKuTfIXYlra+c65FKFAcZrC4vt1CLtBqW2mBy7U868c0L9PZ1g3+WGvA
|
||||
FmnZA6MgUKQE0i0CAwEAAaOBlTCBkjAdBgNVHQ4EFgQUNd238edKw2Tt8tgmXRz4
|
||||
JXhVBKAwHwYDVR0jBBgwFoAUUeBRd0yew4JtInksRTlbz71YwtEwDwYDVR0TAQH/
|
||||
BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwLwYDVR0eAQH/BCUwI6AhMA+GDS5kZXYu
|
||||
YWNtZS5jb20wDoYMZGV2LmFjbWUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQBLljbI
|
||||
ekm5/uhFbc/aCAlomwGkXFvyMXx7eD7Pimzn4H31nYvQ5ha2M0536JC/mH1xi7nK
|
||||
OOMuSBAqjpALoRk4+3O5s6r9BN8KKhcI4jDKHqOSBe38K+Ad06B52yxYyL6YmJwk
|
||||
Zlazf3KvExzUWS0t4ehNuI2HJvvwEitMpOF3hhwAYk3v/x2YBtpglH+yZC4Sfoma
|
||||
ItjFWeD+DA0bVAMJiErz8Pq91avnC8SPpPXiPJVOaBhaNc8po6x6cwSqY6RnI2/K
|
||||
0kUWXXH65Pz0JYru53ALzy4ouwJItcgMvzZPGVaojxEbGDrjXEkWIGresFrw1Ijr
|
||||
IyrQUqWa9wW6ik+IQOb6m3FZYB8jMO7nhop9Ywm9uoSmFRg6RsP2AWHBMYP7lZqw
|
||||
fx3HjrAvc3ycIZ2tSPkdLd5n8YuL31CVpa9aGwT5dYzIVd/eFUrCUIGV2j8XHgkL
|
||||
gMPr8JhNPAG0B4rRpEXmK3HHybo3s0M8i80Lit98xzupNpng97xKT7jJBSinNTdt
|
||||
/2uU7diHQM7aPNmNG+Wu3GXVt/MZuDMSFrh9AHl0A/Y4mNu6KKqRMJuvsfy/j1DD
|
||||
fDGmAkjHrspiorTruphHk+cymJfjAGqZ0l6il4Wi5w4R5jrxnJMhkxbjr/PG5xCS
|
||||
+ZKPPNZbpPIY54oQ2bHkuaQgzJ7us4ZW7gxgbw==
|
||||
-----END CERTIFICATE-----
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE1DCCArygAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwPzELMAkGA1UEBhMCVVMx
|
||||
FzAVBgNVBAoMDnRlc3QxLmFjbWUuY29tMRcwFQYDVQQDDA5JbnRlcm1lZGlhZXRD
|
||||
QTAeFw0xNzA3MTkxNjUwMjBaFw0xNzA3MjkxNjUwMjBaMDUxCzAJBgNVBAYTAlVT
|
||||
MRcwFQYDVQQKDA50ZXN0MS5hY21lLmNvbTENMAsGA1UEAwwEYmxvZzCCASIwDQYJ
|
||||
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKm8P47lABp4+rz2nN+QYrxedbaFVWoF
|
||||
FuoSkqcHsafMwbMrN+kI6wJVtlbwviDvxWFJ92q0H71QNFybTsmof3KUN/kYCp7P
|
||||
+LKhBrN0ttWI5q6v5eDrjN0VdtVdnlZOYmJFbvETOgfK/qXKNRRM8HYW0tdqrtEw
|
||||
CR5dIu53xVUSViBdwXpuy2c5W2mFn1gxTpdW+3hbZsL1pHrU9qPWLtTgl/KY8kjs
|
||||
I7KW1cIcinE4SJomhB5L/4emhxKGY+kEa2+fN9IPjjvKSMOw9kiBKk1GHZcIY5EA
|
||||
O3TIfUk3fysPzi5qA0su/bNtPQy1uXgXS10xUlV7pqRPvHjiNzgFkXUCAwEAAaOB
|
||||
4zCB4DAJBgNVHRMEAjAAMB0GA1UdDgQWBBRVQ91jSOONzVr1VGBdJOlPN+3XxTBg
|
||||
BgNVHSMEWTBXgBQ13bfx50rDZO3y2CZdHPgleFUEoKE7pDkwNzELMAkGA1UEBhMC
|
||||
VVMxFzAVBgNVBAoMDnRlc3QxLmFjbWUuY29tMQ8wDQYDVQQDDAZSb290Q0GCAhAA
|
||||
MA4GA1UdDwEB/wQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAtBgNVHREEJjAk
|
||||
hiJzcGlmZmU6Ly9kZXYuYWNtZS5jb20vcGF0aC9zZXJ2aWNlMA0GCSqGSIb3DQEB
|
||||
CwUAA4ICAQBp2+rtUxt1VmNM/vi6PwoSoYzWFmQ2nc4OM7bsOG4uppU54wRYZ+T7
|
||||
c42EcrpyBgWn+rWHT1Hi6SNcmloKHydaUTZ4pq3IlKKnBNqwivU5BzIxYLDrhR/U
|
||||
wd9s1tgmLvADqkQa1XjjSFn5Auoj1R640ry4qpw8IOusdm6wVhru4ssRnHX4E2uR
|
||||
jQe7b3ws38aZhjtL78Ip0BB4yPxWJRp/WmEoT33QP+cZhA4IYWECxNODr6DSJeq2
|
||||
VNu/6JACGrNfM2Sjt4Wxz+nIa3cKDNCA6PR8StTUTcoQ6ZBzpn+n/Q1xSRIOJz6N
|
||||
hgfkyb9O7HAMdAP+TxehjqG3gh5Ky2DgYMCIZOztVzsuOb1DGJe/kGUKeRJLl2/O
|
||||
QwkctwUOcVIxckNu6OvclriFzvoXObqO77XeCI2V1Vef0wGTWlWNOdbFa4708Y7f
|
||||
5UdwInYQUi87RFDnc1SDU4Jrsv4KzZiv9FCfDg8pCBIdWpWT7DAuI0d7i7PZ+iFt
|
||||
ZZ6sb/YDkyiDXU4ar/dja0FDE2r7jsN9D+FfW49+iDvXr4ELQyhZpW3Zr1Ojwm58
|
||||
CJzjZwbRYiVwPBRsKmiYfO1E7esvw3CmjK5chfz8c40f6/APDro9ZmYNBRv2CnJy
|
||||
t/DtcM/GpAhBbLP9Tk7kPB41v5fRIxVDo50Iz/qvkr37pQ4RsejSFg==
|
||||
-----END CERTIFICATE-----
|
||||
Reference in New Issue
Block a user