Skip to content

Commit a6bb5a8

Browse files
committed
Add attribute support for certificate subject
Fixes #128 Signed-off-by: cornfeedhobo <[email protected]>
1 parent 2b9b71f commit a6bb5a8

File tree

4 files changed

+104
-17
lines changed

4 files changed

+104
-17
lines changed

pkg/apis/v1alpha1/types.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,17 @@ const (
2121
IssuerKindKey = "csi.cert-manager.io/issuer-kind"
2222
IssuerGroupKey = "csi.cert-manager.io/issuer-group"
2323

24-
CommonNameKey = "csi.cert-manager.io/common-name"
24+
LiteralSubjectKey = "csi.cert-manager.io/literal-subject"
25+
CommonNameKey = "csi.cert-manager.io/common-name"
26+
OrganizationsKey = "csi.cert-manager.io/organizations"
27+
OrganizationalUnitsKey = "csi.cert-manager.io/organizationalunits"
28+
CountriesKey = "csi.cert-manager.io/countries"
29+
ProvincesKey = "csi.cert-manager.io/provinces"
30+
LocalitiesKey = "csi.cert-manager.io/localities"
31+
StreetAddressesKey = "csi.cert-manager.io/streetaddresses"
32+
PostalCodesKey = "csi.cert-manager.io/postalcodes"
33+
SerialNumberKey = "csi.cert-manager.io/serialnumber"
34+
2535
DNSNamesKey = "csi.cert-manager.io/dns-names"
2636
IPSANsKey = "csi.cert-manager.io/ip-sans"
2737
URISANsKey = "csi.cert-manager.io/uri-sans"

pkg/apis/validation/validation_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ func Test_ValidateAttributes(t *testing.T) {
3232
expError error
3333
}
3434

35+
var literalSubject = "CN=${POD_NAME}.${POD_NAMESPACE}.svc.cluster.local,OU=0:${POD_NAME}\\;1:${POD_NAMESPACE}\\;2:my-region\\;4:unittest,O=foo.bar.com"
36+
3537
tests := map[string]struct {
3638
attr map[string]string
3739
expErr field.ErrorList
@@ -206,6 +208,18 @@ func Test_ValidateAttributes(t *testing.T) {
206208
field.Invalid(field.NewPath("volumeAttributes", "csi.cert-manager.io/privatekey-file"), "/foobar", "filename must not include '/'"),
207209
},
208210
},
211+
"correct literal-subject should not error": {
212+
attr: map[string]string{
213+
csiapi.IssuerNameKey: "test-issuer",
214+
csiapi.LiteralSubjectKey: literalSubject,
215+
csiapi.CAFileKey: "ca.crt",
216+
csiapi.CertFileKey: "crt.tls",
217+
csiapi.KeyFileKey: "key.tls",
218+
csiapi.DNSNamesKey: "foo.bar.com",
219+
csiapi.KeyEncodingKey: "PKCS8",
220+
},
221+
expErr: nil,
222+
},
209223
}
210224

211225
for name, test := range tests {

pkg/requestgen/generator.go

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import (
2929

3030
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
3131
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
32+
cmpki "github.com/cert-manager/cert-manager/pkg/util/pki"
33+
3234
"github.com/cert-manager/csi-lib/manager"
3335
"github.com/cert-manager/csi-lib/metadata"
3436

@@ -56,32 +58,58 @@ func RequestForMetadata(meta metadata.Metadata) (*manager.CertificateRequestBund
5658
}
5759
}
5860

59-
commonName, err := expand(meta, attrs[csiapi.CommonNameKey])
60-
if err != nil {
61-
return nil, fmt.Errorf("%q: %w", csiapi.CommonNameKey, err)
61+
var request = &x509.CertificateRequest{}
62+
if lSubjStr, ok := attrs[csiapi.LiteralSubjectKey]; ok && len(lSubjStr) > 0 {
63+
lSubjStr, err = expand(meta, lSubjStr)
64+
if err != nil {
65+
return nil, fmt.Errorf("%q: %w", csiapi.LiteralSubjectKey, err)
66+
}
67+
request.RawSubject, err = cmpki.ParseSubjectStringToRawDerBytes(lSubjStr)
68+
if err != nil {
69+
return nil, fmt.Errorf("%q: %w", csiapi.LiteralSubjectKey, err)
70+
}
71+
} else {
72+
request.Subject = pkix.Name{}
73+
request.Subject.CommonName, err = expand(meta, attrs[csiapi.CommonNameKey])
74+
if err != nil {
75+
return nil, fmt.Errorf("%q: %w", csiapi.CommonNameKey, err)
76+
}
77+
if len(attrs[csiapi.SerialNumberKey]) > 0 {
78+
request.Subject.SerialNumber = attrs[csiapi.SerialNumberKey]
79+
}
80+
for k, v := range map[*[]string]string{
81+
&request.Subject.Organization: csiapi.OrganizationsKey,
82+
&request.Subject.OrganizationalUnit: csiapi.OrganizationalUnitsKey,
83+
&request.Subject.Country: csiapi.CountriesKey,
84+
&request.Subject.Province: csiapi.ProvincesKey,
85+
&request.Subject.Locality: csiapi.LocalitiesKey,
86+
&request.Subject.StreetAddress: csiapi.StreetAddressesKey,
87+
&request.Subject.PostalCode: csiapi.PostalCodesKey,
88+
} {
89+
if len(attrs[v]) > 0 {
90+
var e, err = expand(meta, attrs[v])
91+
if err != nil {
92+
return nil, fmt.Errorf("%q: %w", v, err)
93+
}
94+
*k = strings.Split(e, ",")
95+
}
96+
}
6297
}
63-
dns, err := parseDNSNames(meta, attrs[csiapi.DNSNamesKey])
98+
request.DNSNames, err = parseDNSNames(meta, attrs[csiapi.DNSNamesKey])
6499
if err != nil {
65100
return nil, fmt.Errorf("%q: %w", csiapi.DNSNamesKey, err)
66101
}
67-
uris, err := parseURIs(meta, attrs[csiapi.URISANsKey])
102+
request.IPAddresses, err = parseIPAddresses(attrs[csiapi.IPSANsKey])
68103
if err != nil {
69-
return nil, fmt.Errorf("%q: %w", csiapi.URISANsKey, err)
104+
return nil, fmt.Errorf("%q: %w", csiapi.IPSANsKey, err)
70105
}
71-
ips, err := parseIPAddresses(attrs[csiapi.IPSANsKey])
106+
request.URIs, err = parseURIs(meta, attrs[csiapi.URISANsKey])
72107
if err != nil {
73-
return nil, fmt.Errorf("%q: %w", csiapi.IPSANsKey, err)
108+
return nil, fmt.Errorf("%q: %w", csiapi.URISANsKey, err)
74109
}
75110

76111
return &manager.CertificateRequestBundle{
77-
Request: &x509.CertificateRequest{
78-
Subject: pkix.Name{
79-
CommonName: commonName,
80-
},
81-
DNSNames: dns,
82-
IPAddresses: ips,
83-
URIs: uris,
84-
},
112+
Request: request,
85113
IsCA: strings.ToLower(attrs[csiapi.IsCAKey]) == "true",
86114
Namespace: attrs[csiapi.K8sVolumeContextKeyPodNamespace],
87115
Duration: duration,

pkg/requestgen/generator_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"errors"
2323
"net"
2424
"net/url"
25+
"strings"
2526
"testing"
2627
"time"
2728

@@ -31,6 +32,9 @@ import (
3132

3233
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
3334
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
35+
cmpki "github.com/cert-manager/cert-manager/pkg/util/pki"
36+
37+
csiapi "github.com/cert-manager/csi-driver/pkg/apis/v1alpha1"
3438
)
3539

3640
func Test_RequestForMetadata(t *testing.T) {
@@ -52,6 +56,12 @@ func Test_RequestForMetadata(t *testing.T) {
5256
return puri
5357
}
5458

59+
var literalSubject = "CN=my-pod.my-namespace.svc.cluster.local,OU=0:my-pod\\;1:my-namespace\\;2:my-region\\;4:unittest,O=foo.bar.com"
60+
var rawLiteralSubject, err = cmpki.ParseSubjectStringToRawDerBytes(literalSubject)
61+
if err != nil {
62+
assert.NoError(t, err)
63+
}
64+
5565
tests := map[string]struct {
5666
meta metadata.Metadata
5767
expRequest *manager.CertificateRequestBundle
@@ -174,6 +184,31 @@ func Test_RequestForMetadata(t *testing.T) {
174184
},
175185
expErr: false,
176186
},
187+
"a metadata with literal subject set should be returned": {
188+
meta: baseMetadataWith(metadata.Metadata{VolumeContext: map[string]string{
189+
csiapi.IssuerNameKey: "my-issuer",
190+
csiapi.LiteralSubjectKey: literalSubject,
191+
}}),
192+
expRequest: &manager.CertificateRequestBundle{
193+
Request: &x509.CertificateRequest{RawSubject: rawLiteralSubject},
194+
Usages: cmapi.DefaultKeyUsages(),
195+
Namespace: "my-namespace",
196+
IssuerRef: cmmeta.ObjectReference{
197+
Name: "my-issuer",
198+
Kind: "Issuer",
199+
Group: "cert-manager.io",
200+
},
201+
Duration: cmapi.DefaultCertificateDuration,
202+
},
203+
expErr: false,
204+
},
205+
"a metadata with incorrect literal subject set should error": {
206+
meta: baseMetadataWith(metadata.Metadata{VolumeContext: map[string]string{
207+
csiapi.IssuerNameKey: "my-issuer",
208+
csiapi.LiteralSubjectKey: strings.Replace(literalSubject, ";", "&", -1),
209+
}}),
210+
expErr: true,
211+
},
177212
}
178213

179214
for name, test := range tests {

0 commit comments

Comments
 (0)