mirror of
https://github.com/square/certigo.git
synced 2026-10-21 05:21:07 +00:00
Merge pull request #168 from square/cs/go-1.11
Use Go 1.11, use built-in functions for URI names
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- '1.10.x'
|
||||
- '1.11.x'
|
||||
|
||||
install:
|
||||
- go get github.com/Masterminds/glide
|
||||
|
||||
Generated
-2
@@ -27,8 +27,6 @@ imports:
|
||||
version: 6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c
|
||||
- name: github.com/mwitkow/go-http-dialer
|
||||
version: 378f744fb2b81a6b96e3f40cde4f3bcab5a9cff0
|
||||
- name: github.com/spiffe/go-spiffe
|
||||
version: 2bb3101d62b4bea6371d792e818360e3f056867b
|
||||
- name: golang.org/x/crypto
|
||||
version: b2aa35443fbc700ab74c586ae79b81c171851023
|
||||
subpackages:
|
||||
|
||||
@@ -12,5 +12,4 @@ import:
|
||||
version: ^1.2.0
|
||||
- package: github.com/Masterminds/sprig
|
||||
version: ^2.12.0
|
||||
- package: github.com/spiffe/go-spiffe
|
||||
- package: github.com/mwitkow/go-http-dialer
|
||||
|
||||
+3
-6
@@ -32,8 +32,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spiffe/go-spiffe/uri"
|
||||
)
|
||||
|
||||
var keyUsages = []x509.KeyUsage{
|
||||
@@ -244,12 +242,11 @@ func createSimpleCertificate(name string, cert *x509.Certificate) simpleCertific
|
||||
PEM: string(pem.EncodeToMemory(EncodeX509ToPEM(cert, nil))),
|
||||
}
|
||||
|
||||
uriNames, err := uri.GetURINamesFromCertificate(cert)
|
||||
if err == nil {
|
||||
out.URINames = uriNames
|
||||
for _, uri := range cert.URIs {
|
||||
out.URINames = append(out.URINames, uri.String())
|
||||
}
|
||||
|
||||
out.Warnings = certWarnings(cert, uriNames)
|
||||
out.Warnings = certWarnings(cert, out.URINames)
|
||||
|
||||
if cert.BasicConstraintsValid {
|
||||
out.BasicConstraints = &basicConstraints{
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
version: 2
|
||||
|
||||
jobs:
|
||||
build:
|
||||
machine: true
|
||||
working_directory: ~
|
||||
steps:
|
||||
- checkout
|
||||
- run: make test
|
||||
|
||||
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
* @amartinezfayo @evan2645
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
Copyright 2017 The SPIFFE Project & 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.
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
ROOT := github.com/spiffe/go-spiffe
|
||||
PACKAGE_LIST := uri spiffe
|
||||
|
||||
test: vet
|
||||
@for p in $(PACKAGE_LIST); do \
|
||||
go test $(ROOT)/$$p || exit 1; \
|
||||
done
|
||||
|
||||
vet:
|
||||
@for p in $(PACKAGE_LIST); do \
|
||||
go vet $(ROOT)/$$p; \
|
||||
done
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
# go-spiffe library [](https://godoc.org/github.com/spiffe/go-spiffe)
|
||||
|
||||
## Overview
|
||||
|
||||
The go-spiffe library provides functionality to parse and verify SPIFFE
|
||||
identities encoded in X.509 certificates as described in the
|
||||
[SPIFFE Standards](https://github.com/spiffe/spiffe/tree/master/standards).
|
||||
|
||||
## Installing it
|
||||
```shell
|
||||
go get -u -v github.com/spiffe/go-spiffe
|
||||
```
|
||||
|
||||
## Importing it in your Go code
|
||||
|
||||
See examples in [examples_test.go](./example_test.go)
|
||||
or visit the [GoDoc](https://godoc.org/github.com/spiffe/go-spiffe) for more information
|
||||
|
||||
## Installing the command line interface
|
||||
The command line interface can be used to retrieve and view URIs stored
|
||||
in the SAN extension of certificates
|
||||
|
||||
```shell
|
||||
go get -u -v github.com/spiffe/go-spiffe/cmd/spiffe
|
||||
spiffe testdata/leaf.cert.pem $HOME/certs/proj.pem
|
||||
Path:: #1: "testdata/leaf.cert.pem"
|
||||
URI #1: "spiffe://dev.acme.com/path/service"
|
||||
```
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
spiffe "github.com/spiffe/go-spiffe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Make log not print out time information
|
||||
log.SetFlags(0)
|
||||
|
||||
if len(os.Args) <= 1 {
|
||||
log.Fatalf("\033[31mexpecting path [paths...] e.g\033[00m\n\tspiffe /var/lib/letsencrypt/spiffe.pem $HOME/Desktop/certs/cert.pem\033[00m\n")
|
||||
}
|
||||
|
||||
seenPaths := make(map[string]bool)
|
||||
args := os.Args[1:]
|
||||
for i, path := range args {
|
||||
if _, seen := seenPaths[path]; seen {
|
||||
continue
|
||||
}
|
||||
|
||||
seenPaths[path] = true
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Printf("\n#%d: err=%v\n", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
uris, err := spiffe.FGetURINamesFromPEM(f)
|
||||
_ = f.Close()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("\n#%d: parseErr=%v\n", i, err)
|
||||
continue
|
||||
}
|
||||
if len(uris) == 0 {
|
||||
log.Printf("\n#%d: no uris could be parsed\n", i)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("Path:: #%d: %q\n", i+1, path)
|
||||
for j, uri := range uris {
|
||||
log.Printf("\tURI #%d: %q\n", j+1, uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package spiffe
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
|
||||
"github.com/spiffe/go-spiffe/uri"
|
||||
)
|
||||
|
||||
// Tries to match a SPIFFE ID, given a certificate
|
||||
func MatchID(ids []string, cert *x509.Certificate) error {
|
||||
parsedIDs, err := uri.GetURINamesFromCertificate(cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, parsedID := range parsedIDs {
|
||||
for _, id := range ids {
|
||||
if parsedID == id {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("SPIFFE ID mismatch")
|
||||
}
|
||||
|
||||
// Verify a SPIFFE certificate and its certification path
|
||||
func VerifyCertificate(leaf *x509.Certificate, intermediates *x509.CertPool, roots *x509.CertPool) error {
|
||||
verifyOpts := x509.VerifyOptions{
|
||||
Intermediates: intermediates,
|
||||
Roots: roots,
|
||||
}
|
||||
|
||||
// TODO: SPIFFE-specific validation of leaf and verified chain
|
||||
_, err := leaf.Verify(verifyOpts)
|
||||
return err
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
-----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
@@ -1,28 +0,0 @@
|
||||
-----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-----
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
|
||||
"github.com/spiffe/go-spiffe/spiffe"
|
||||
)
|
||||
|
||||
type TLSPeer struct {
|
||||
// Slice of permitted SPIFFE IDs
|
||||
SpiffeIDs []string
|
||||
|
||||
TrustRoots *x509.CertPool
|
||||
}
|
||||
|
||||
// NewTLSConfig creates a SPIFFE-compatible TLS configuration.
|
||||
// We are opinionated towards mutual TLS. If you don't want
|
||||
// mutual TLS, you'll need to update the returned config.
|
||||
//
|
||||
// `certs` contains one or more certificates to present to the
|
||||
// other side of the connection, leaf first.
|
||||
func (t *TLSPeer) NewTLSConfig(certs []tls.Certificate) *tls.Config {
|
||||
config := &tls.Config{
|
||||
// Disable validation/verification because we perform
|
||||
// this step with custom logic in `verifyPeerCertificate`
|
||||
ClientAuth: tls.RequireAnyClientCert,
|
||||
InsecureSkipVerify: true,
|
||||
VerifyPeerCertificate: t.verifyPeerCertificate,
|
||||
Certificates: certs,
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// verifyPeerCertificate serves callbacks from TLS listeners/dialers. It performs
|
||||
// SPIFFE-specific validation steps on behalf of the golang TLS library
|
||||
func (t *TLSPeer) verifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) (err error) {
|
||||
// First, parse all received certs
|
||||
var certs []*x509.Certificate
|
||||
for _, rawCert := range rawCerts {
|
||||
cert, err := x509.ParseCertificate(rawCert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
certs = append(certs, cert)
|
||||
}
|
||||
|
||||
// Perform path validation
|
||||
// Leaf is the first off the wire:
|
||||
// https://tools.ietf.org/html/rfc5246#section-7.4.2
|
||||
intermediates := x509.NewCertPool()
|
||||
for _, intermediate := range certs[1:] {
|
||||
intermediates.AddCert(intermediate)
|
||||
}
|
||||
err = spiffe.VerifyCertificate(certs[0], intermediates, t.TrustRoots)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Look for a known SPIFFE ID in the leaf
|
||||
err = spiffe.MatchID(t.SpiffeIDs, certs[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we are here, then all is well
|
||||
return nil
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
package uri
|
||||
|
||||
import(
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
)
|
||||
|
||||
var OidExtensionSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17}
|
||||
var OidExtensionKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 15}
|
||||
|
||||
// GetExtensionsFromAsn1ObjectIdentifier takes a parsed X.509 certificate and an OID
|
||||
// and gets the extensions that match the given OID
|
||||
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
|
||||
}
|
||||
|
||||
// GetKeyUsageExtensionsFromCertificate takes a parsed X.509 certificate and gets the Key Usage extensions
|
||||
func GetKeyUsageExtensionsFromCertificate(cert *x509.Certificate) (extension []pkix.Extension) {
|
||||
return GetExtensionsFromAsn1ObjectIdentifier(cert, OidExtensionKeyUsage)
|
||||
}
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
package uri
|
||||
|
||||
import (
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
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 uris, err
|
||||
} else if len(rest) != 0 {
|
||||
err = errors.New("x509: trailing data after X.509 extension")
|
||||
return uris, err
|
||||
}
|
||||
if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 {
|
||||
err = asn1.StructuralError{Msg: "bad SAN sequence"}
|
||||
return uris, err
|
||||
}
|
||||
|
||||
rest = seq.Bytes
|
||||
for len(rest) > 0 {
|
||||
var v asn1.RawValue
|
||||
rest, err = asn1.Unmarshal(rest, &v)
|
||||
if err != nil {
|
||||
return uris, err
|
||||
}
|
||||
if v.Tag == 6 {
|
||||
uris = append(uris, string(v.Bytes))
|
||||
}
|
||||
}
|
||||
|
||||
return uris, err
|
||||
}
|
||||
|
||||
// GetURINamesFromCertificate 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 uris, err
|
||||
}
|
||||
}
|
||||
|
||||
return uris, nil
|
||||
}
|
||||
|
||||
// GetURINamesFromPEM parses a PEM-encoded X.509 certificate and gets the URIs from the SAN extension.
|
||||
func GetURINamesFromPEM(encodedCertificate string) (uris []string, err error) {
|
||||
return uriNamesFromPEM([]byte(encodedCertificate))
|
||||
}
|
||||
|
||||
func uriNamesFromPEM(encodedCertificate []byte) (uris []string, err error) {
|
||||
block, _ := pem.Decode(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)
|
||||
}
|
||||
|
||||
// FGetURINamesFromPEM retrieves URIs from the SAN extension of a
|
||||
// PEM-encoded X.509 certificate, whose content is in the provided io.Reader.
|
||||
func FGetURINamesFromPEM(f io.Reader) (uris []string, err error) {
|
||||
blob, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uriNamesFromPEM(blob)
|
||||
}
|
||||
|
||||
// GetURINamesFromExtensions retrieves URIs from the SAN extension of a slice of extensions
|
||||
func GetURINamesFromExtensions(extensions *[]pkix.Extension) (uris []string, err error) {
|
||||
for _, ext := range *extensions {
|
||||
if ext.Id.Equal(OidExtensionSubjectAltName) {
|
||||
uris, err = getURINamesFromSANExtension(ext.Value)
|
||||
if err != nil {
|
||||
return uris, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uris, nil
|
||||
}
|
||||
|
||||
// MarshalUriSANs takes URI strings and returns the ASN.1 structure to be used
|
||||
// in the Value field for the SAN Extension
|
||||
func MarshalUriSANs(uris []string) (derBytes []byte, err error) {
|
||||
var rawValues []asn1.RawValue
|
||||
for _, name := range uris {
|
||||
rawValues = append(rawValues, asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)})
|
||||
}
|
||||
|
||||
return asn1.Marshal(rawValues)
|
||||
}
|
||||
Reference in New Issue
Block a user