Skip to content

Commit 3d230e6

Browse files
Add a new ClientOption to handle PEM encoded certs (#40)
* Add a new ClientOption to handle PEM encoded certs WithPEMEncodedCertBundle takes a byte array containing PEM bkocks, parses the certificates from the blocks into x509.Certificate type and adds them to the cert pool used for TLS Authentication. * Appease the linter gofumpt
1 parent c9e9960 commit 3d230e6

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
### Added
99
- Add `AdditionalTrustBundle` property to the `NutanixPrismEndpoint` struct in environment/credential/types.go
1010
- Add `AdditionalTrustBundle` property to the `ManagementEndpoint` struct in environment/types/types/go
11+
- Add `WithPEMEncodedCertBundle` ClientOption for handling PEM Blocks in the v3 Constructor
1112

1213
### Changed
1314
- Add license header to generated file and add a makefile target for generate

v3/v3.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package v3
22

33
import (
44
"crypto/x509"
5+
"encoding/pem"
56
"fmt"
67
"net/http"
78

@@ -35,6 +36,25 @@ func WithCertificate(certificate *x509.Certificate) ClientOption {
3536
}
3637
}
3738

39+
// WithPEMEncodedCertBundle sets the certificates for the client
40+
func WithPEMEncodedCertBundle(certBundle []byte) ClientOption {
41+
return func(c *Client) error {
42+
for block, rest := pem.Decode(certBundle); block != nil; block, rest = pem.Decode(rest) {
43+
if block.Type != "CERTIFICATE" {
44+
return fmt.Errorf("unexpected PEM block type %q: was expecting CERTIFICATE", block.Type)
45+
}
46+
certs, err := x509.ParseCertificates(block.Bytes)
47+
if err != nil {
48+
return err
49+
}
50+
for _, cert := range certs {
51+
c.clientOpts = append(c.clientOpts, internal.WithCertificate(cert))
52+
}
53+
}
54+
return nil
55+
}
56+
}
57+
3858
// WithRoundTripper overrides the transport for the underlying http client
3959
// Overriding transport is useful for testing against API Mocks
4060
// This is not recommended for production use

v3/v3_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"testing"
55

66
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
78

89
"github.com/nutanix-cloud-native/prism-go-client"
910
)
@@ -38,3 +39,64 @@ func TestNewV3Client(t *testing.T) {
3839
assert.Nil(t, v3Client)
3940
assert.EqualError(t, err, "username, password and endpoint are required")
4041
}
42+
43+
func TestNewV3ClientWithPEMEncodedCertBundle(t *testing.T) {
44+
// verifies positive client creation
45+
cred := prismgoclient.Credentials{
46+
URL: "foo.com",
47+
Username: "username",
48+
Password: "password",
49+
Port: "9440",
50+
Endpoint: "foo.com",
51+
}
52+
certBundle := `-----BEGIN CERTIFICATE-----
53+
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
54+
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
55+
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
56+
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
57+
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
58+
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
59+
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
60+
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
61+
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
62+
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
63+
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
64+
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
65+
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
66+
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
67+
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
68+
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
69+
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
70+
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
71+
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
72+
-----END CERTIFICATE-----
73+
-----BEGIN CERTIFICATE-----
74+
MIIEYDCCA0igAwIBAgILBAAAAAABL07hRQwwDQYJKoZIhvcNAQEFBQAwVzELMAkG
75+
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
76+
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMTA0MTMxMDAw
77+
MDBaFw0yMjA0MTMxMDAwMDBaMF0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
78+
YWxTaWduIG52LXNhMTMwMQYDVQQDEypHbG9iYWxTaWduIE9yZ2FuaXphdGlvbiBW
79+
YWxpZGF0aW9uIENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
80+
AQDdNR3yIFQmGtDvpW+Bdllw3Of01AMkHyQOnSKf1Ccyeit87ovjYWI4F6+0S3qf
81+
ZyEcLZVUunm6tsTyDSF0F2d04rFkCJlgePtnwkv3J41vNnbPMYzl8QbX3FcOW6zu
82+
zi2rqqlwLwKGyLHQCAeV6irs0Z7kNlw7pja1Q4ur944+ABv/hVlrYgGNguhKujiz
83+
4MP0bRmn6gXdhGfCZsckAnNate6kGdn8AM62pI3ffr1fsjqdhDFPyGMM5NgNUqN+
84+
ARvUZ6UYKOsBp4I82Y4d5UcNuotZFKMfH0vq4idGhs6dOcRmQafiFSNrVkfB7cVT
85+
5NSAH2v6gEaYsgmmD5W+ZoiTAgMBAAGjggElMIIBITAOBgNVHQ8BAf8EBAMCAQYw
86+
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUXUayjcRLdBy77fVztjq3OI91
87+
nn4wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3
88+
Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMDMGA1UdHwQsMCowKKAmoCSGImh0
89+
dHA6Ly9jcmwuZ2xvYmFsc2lnbi5uZXQvcm9vdC5jcmwwPQYIKwYBBQUHAQEEMTAv
90+
MC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEw
91+
HwYDVR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQAD
92+
ggEBABvgiADHBREc/6stSEJSzSBo53xBjcEnxSxZZ6CaNduzUKcbYumlO/q2IQen
93+
fPMOK25+Lk2TnLryhj5jiBDYW2FQEtuHrhm70t8ylgCoXtwtI7yw07VKoI5lkS/Z
94+
9oL2dLLffCbvGSuXL+Ch7rkXIkg/pfcNYNUNUUflWP63n41edTzGQfDPgVRJEcYX
95+
pOBWYdw9P91nbHZF2krqrhqkYE/Ho9aqp9nNgSvBZnWygI/1h01fwlr1kMbawb30
96+
hag8IyrhFHvBN91i0ZJsumB9iOQct+R2UTjEqUdOqCsukNK1OFHrwZyKarXMsh3o
97+
wFZUTKiL8IkyhtyTMr5NGvo1dbU=
98+
-----END CERTIFICATE-----`
99+
v3Client, err := NewV3Client(cred, WithPEMEncodedCertBundle([]byte(certBundle)))
100+
require.NoError(t, err)
101+
assert.NotNil(t, v3Client)
102+
}

0 commit comments

Comments
 (0)