-
Notifications
You must be signed in to change notification settings - Fork 0
/
certificate.go
127 lines (104 loc) · 3.13 KB
/
certificate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright 2020 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package pki
import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"math/big"
"github.com/juju/errors"
"github.com/juju/utils/v3"
)
// CSRToCertificate copies all fields from a CertificateRequest into a new x509
// Certificate. No policy check is performed this is just a straight 1 to 1
// copy.
func CSRToCertificate(csr *x509.CertificateRequest) *x509.Certificate {
cert := &x509.Certificate{}
cert.Subject = csr.Subject
cert.Extensions = csr.Extensions
cert.ExtraExtensions = csr.ExtraExtensions
cert.DNSNames = csr.DNSNames
cert.EmailAddresses = csr.EmailAddresses
cert.IPAddresses = csr.IPAddresses
cert.URIs = csr.URIs
return cert
}
func assetTagCertificate(cert *x509.Certificate) error {
uuid, err := utils.NewUUID()
if err != nil {
return errors.Annotate(err, "failed to generate new certificate uuid")
}
serialNumber, err := newSerialNumber()
if err != nil {
return errors.Annotate(err,
"failed to generate new certificate serial number")
}
cert.SerialNumber = serialNumber
cert.Subject.SerialNumber = uuid.String()
return nil
}
// MakeX509NameFromDefaults constructs a new x509 name from the merging of a
// default and request name. Fields not set in the request name
// will be copied from the default name.
func MakeX509NameFromDefaults(template, request *pkix.Name) pkix.Name {
rval := pkix.Name{}
if template == nil {
template = &pkix.Name{}
}
rval.Country = request.Country
if len(rval.Country) == 0 {
rval.Country = template.Country
}
rval.Organization = request.Organization
if len(rval.Organization) == 0 {
rval.Organization = template.Organization
}
rval.OrganizationalUnit = request.OrganizationalUnit
if len(rval.OrganizationalUnit) == 0 {
rval.OrganizationalUnit = template.OrganizationalUnit
}
rval.Locality = request.Locality
if len(rval.Locality) == 0 {
rval.Locality = template.Locality
}
rval.Province = request.Province
if len(rval.Province) == 0 {
rval.Province = template.Province
}
rval.StreetAddress = request.StreetAddress
if len(rval.StreetAddress) == 0 {
rval.StreetAddress = template.StreetAddress
}
rval.PostalCode = request.PostalCode
if len(rval.PostalCode) == 0 {
rval.PostalCode = template.PostalCode
}
rval.SerialNumber = request.SerialNumber
if rval.SerialNumber == "" {
rval.SerialNumber = template.SerialNumber
}
rval.CommonName = request.CommonName
if rval.CommonName == "" {
rval.CommonName = template.CommonName
}
rval.Names = request.Names
if len(rval.Names) == 0 {
rval.Names = template.Names
}
rval.ExtraNames = request.ExtraNames
if len(rval.ExtraNames) == 0 {
rval.ExtraNames = template.ExtraNames
}
return rval
}
// newSerialNumber returns a new random serial number suitable for use in a
// certificate.
func newSerialNumber() (*big.Int, error) {
// A serial number can be up to 20 octets in size.
// https://tools.ietf.org/html/rfc5280#section-4.1.2.2
n, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 8*20))
if err != nil {
return nil, errors.Annotatef(err, "failed to generate serial number")
}
return n, nil
}