github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/pki/pem_test.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package pki_test 5 6 import ( 7 "crypto" 8 "crypto/rsa" 9 "crypto/x509" 10 "encoding/pem" 11 "strings" 12 13 jc "github.com/juju/testing/checkers" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/pki" 17 ) 18 19 type PEMSuite struct { 20 signer crypto.Signer 21 } 22 23 var _ = gc.Suite(&PEMSuite{}) 24 25 func (p *PEMSuite) SetUpTest(c *gc.C) { 26 signer, err := pki.DefaultKeyProfile() 27 c.Assert(err, jc.ErrorIsNil) 28 p.signer = signer 29 } 30 31 func (p *PEMSuite) TestCertificateToPemString(c *gc.C) { 32 ca, err := pki.NewCA("juju-test-ca", p.signer) 33 c.Assert(err, jc.ErrorIsNil) 34 35 certString, err := pki.CertificateToPemString(map[string]string{ 36 "test": "test-header", 37 }, ca) 38 c.Assert(err, jc.ErrorIsNil) 39 c.Assert(len(certString), jc.GreaterThan, 0) 40 //TODO re-enable headers on certificate to pem when Juju upgrade 41 //CAAS mongo to something compiled with latest openssl. Currently 42 //not all our Openssl versions support pem headers. 43 //c.Assert(strings.Contains(certString, "test: test-header"), jc.IsTrue) 44 c.Assert(strings.Contains(certString, "BEGIN CERTIFICATE"), jc.IsTrue) 45 c.Assert(strings.Contains(certString, "END CERTIFICATE"), jc.IsTrue) 46 } 47 48 func (p *PEMSuite) TestCertificateToPemWriter(c *gc.C) { 49 ca, err := pki.NewCA("juju-test-ca", p.signer) 50 c.Assert(err, jc.ErrorIsNil) 51 52 builder := strings.Builder{} 53 err = pki.CertificateToPemWriter(&builder, map[string]string{ 54 "test": "test-header", 55 }, ca) 56 c.Assert(err, jc.ErrorIsNil) 57 certString := builder.String() 58 c.Assert(len(certString), jc.GreaterThan, 0) 59 //TODO re-enable headers on certificate to pem when Juju upgrade 60 //CAAS mongo to something compiled with latest openssl. Currently 61 //not all our Openssl versions support pem headers. 62 //c.Assert(strings.Contains(certString, "test: test-header"), jc.IsTrue) 63 c.Assert(strings.Contains(certString, "BEGIN CERTIFICATE"), jc.IsTrue) 64 c.Assert(strings.Contains(certString, "END CERTIFICATE"), jc.IsTrue) 65 } 66 67 func (p *PEMSuite) TestSignerToPemString(c *gc.C) { 68 pemKey, err := pki.SignerToPemString(p.signer) 69 c.Assert(err, jc.ErrorIsNil) 70 c.Assert(len(pemKey), jc.GreaterThan, 0) 71 c.Assert(strings.Contains(pemKey, "BEGIN PRIVATE KEY"), jc.IsTrue) 72 c.Assert(strings.Contains(pemKey, "END PRIVATE KEY"), jc.IsTrue) 73 } 74 75 func (p *PEMSuite) TestSignerToPemWriter(c *gc.C) { 76 builder := strings.Builder{} 77 err := pki.SignerToPemWriter(&builder, p.signer) 78 pemKey := builder.String() 79 c.Assert(err, jc.ErrorIsNil) 80 c.Assert(len(pemKey), jc.GreaterThan, 0) 81 c.Assert(strings.Contains(pemKey, "BEGIN PRIVATE KEY"), jc.IsTrue) 82 c.Assert(strings.Contains(pemKey, "END PRIVATE KEY"), jc.IsTrue) 83 } 84 85 func (p *PEMSuite) TestSignerFromPKCS8Pem(c *gc.C) { 86 tests := []struct { 87 Name string 88 SignerFn func() (crypto.Signer, error) 89 }{ 90 { 91 Name: "ECDSAP224", 92 SignerFn: pki.ECDSAP224, 93 }, 94 { 95 Name: "ECDSAP256", 96 SignerFn: pki.ECDSAP256, 97 }, 98 { 99 Name: "ECDSAP384", 100 SignerFn: pki.ECDSAP384, 101 }, 102 { 103 Name: "RSA2048", 104 SignerFn: pki.RSA2048, 105 }, 106 { 107 Name: "RSA3072", 108 SignerFn: pki.RSA3072, 109 }, 110 } 111 112 for _, test := range tests { 113 signer, err := test.SignerFn() 114 c.Assert(err, jc.ErrorIsNil) 115 der, err := x509.MarshalPKCS8PrivateKey(signer) 116 c.Assert(err, jc.ErrorIsNil) 117 block := &pem.Block{ 118 Type: pki.PEMTypePKCS8, 119 Bytes: der, 120 } 121 122 signerPem, err := pki.UnmarshalSignerFromPemBlock(block) 123 c.Assert(err, jc.ErrorIsNil) 124 c.Assert(signerPem, jc.DeepEquals, signer) 125 } 126 } 127 128 func (p *PEMSuite) TestSignerFromPKCS1Pem(c *gc.C) { 129 tests := []struct { 130 Name string 131 SignerFn func() (crypto.Signer, error) 132 }{ 133 { 134 Name: "RSA2048", 135 SignerFn: pki.RSA2048, 136 }, 137 { 138 Name: "RSA3072", 139 SignerFn: pki.RSA3072, 140 }, 141 } 142 143 for _, test := range tests { 144 signer, err := test.SignerFn() 145 c.Assert(err, jc.ErrorIsNil) 146 rsaKey, ok := signer.(*rsa.PrivateKey) 147 c.Assert(ok, gc.Equals, true) 148 149 der := x509.MarshalPKCS1PrivateKey(rsaKey) 150 block := &pem.Block{ 151 Type: pki.PEMTypePKCS1, 152 Bytes: der, 153 } 154 155 signerPem, err := pki.UnmarshalSignerFromPemBlock(block) 156 c.Assert(err, jc.ErrorIsNil) 157 c.Assert(signerPem, jc.DeepEquals, signer) 158 } 159 } 160 161 func (p *PEMSuite) TestFingerprint(c *gc.C) { 162 pemCertStr := `-----BEGIN CERTIFICATE----- 163 MIICBjCCAa2gAwIBAgIVAPIfbVbfSiFAz9eOg1YNuQDakGxuMAoGCCqGSM49BAMC 164 MCExDTALBgNVBAoTBEp1anUxEDAOBgNVBAMTB2p1anUtY2EwHhcNMjAwNDAxMDQz 165 NTEwWhcNMzAwNDAxMDQ0MDEwWjBtMQ0wCwYDVQQKEwRKdWp1MS0wKwYDVQQDEyRK 166 dWp1IHNlcnZlciBjZXJ0aWZpY2F0ZSAtIGNvbnRyb2xsZXIxLTArBgNVBAUTJDUz 167 NmE4MjBhLWM1Y2QtNGY4Mi04ODkzLTk4OTU1MTNhZmExMjBZMBMGByqGSM49AgEG 168 CCqGSM49AwEHA0IABBxmIHbv7oMJidNfe4EyKgnVx/NrtjdJ94jro6nCSrLukXuj 169 tipXQyRUVdjzoVnbJ16YS1m0+WpTbWx8uPDPp2GjdjB0MHIGA1UdEQRrMGmCCWxv 170 Y2FsaG9zdIIOanVqdS1hcGlzZXJ2ZXKCDGp1anUtbW9uZ29kYoIIYW55dGhpbmeC 171 NGNvbnRyb2xsZXItc2VydmljZS5jb250cm9sbGVyLW1pY3JvazhzLWxvY2FsaG9z 172 dC5zdmMwCgYIKoZIzj0EAwIDRwAwRAIgDiRHSIxUmxr+LE+Ja9LENbgv/QmC7XFD 173 kBzDYg/oNisCIAx2LGL0r19fcn1rrVEMUrSMI4Dy3tJ0UEVgSbYhBGBA 174 -----END CERTIFICATE----- 175 ` 176 fingerPrint, remain, err := pki.Fingerprint([]byte(pemCertStr)) 177 c.Assert(err, jc.ErrorIsNil) 178 c.Assert(len(remain), gc.Equals, 0) 179 c.Assert(fingerPrint, gc.Equals, "C7:23:B1:3B:CE:26:BA:55:FF:3B:A0:8F:9D:98:E1:06:9A:70:D1:33:AF:D2:AF:22:F3:28:C0:B4:3B:0E:44:5B") 180 } 181 182 func (p *PEMSuite) TestIsCAPem(c *gc.C) { 183 tests := []struct { 184 pemStr string 185 result bool 186 }{ 187 { 188 pemStr: `-----BEGIN CERTIFICATE----- 189 MIIBaDCCAQ2gAwIBAgIUQ8AAvRcOsUeMNS2JlgcNaHTttqUwCgYIKoZIzj0EAwIw 190 ITENMAsGA1UEChMESnVqdTEQMA4GA1UEAxMHanVqdS1jYTAeFw0yMDA0MDEwNTE1 191 MDJaFw0zMDA0MDEwNTIwMDJaMCExDTALBgNVBAoTBEp1anUxEDAOBgNVBAMTB2p1 192 anUtY2EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS2dFyd3vCw+E9xslHp21VZ 193 DqDzdyVhfOrWnDjgWoIG5mOIyV+KGXtib9ivcP11MUdZ8NbnL0+jVhYpGfU1U2OH 194 oyMwITAOBgNVHQ8BAf8EBAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQD 195 AgNJADBGAiEAvn0RqCuOGkR/0bng/vUD+VXa0ND7BfPDVm8XH/9QdwkCIQCKuTvK 196 9dvUdLCxPEraeZLvK12mioTCZzHXQA1crmQskA== 197 -----END CERTIFICATE-----`, 198 result: true, 199 }, 200 { 201 pemStr: `-----BEGIN CERTIFICATE----- 202 MIICBjCCAa2gAwIBAgIVAPIfbVbfSiFAz9eOg1YNuQDakGxuMAoGCCqGSM49BAMC 203 MCExDTALBgNVBAoTBEp1anUxEDAOBgNVBAMTB2p1anUtY2EwHhcNMjAwNDAxMDQz 204 NTEwWhcNMzAwNDAxMDQ0MDEwWjBtMQ0wCwYDVQQKEwRKdWp1MS0wKwYDVQQDEyRK 205 dWp1IHNlcnZlciBjZXJ0aWZpY2F0ZSAtIGNvbnRyb2xsZXIxLTArBgNVBAUTJDUz 206 NmE4MjBhLWM1Y2QtNGY4Mi04ODkzLTk4OTU1MTNhZmExMjBZMBMGByqGSM49AgEG 207 CCqGSM49AwEHA0IABBxmIHbv7oMJidNfe4EyKgnVx/NrtjdJ94jro6nCSrLukXuj 208 tipXQyRUVdjzoVnbJ16YS1m0+WpTbWx8uPDPp2GjdjB0MHIGA1UdEQRrMGmCCWxv 209 Y2FsaG9zdIIOanVqdS1hcGlzZXJ2ZXKCDGp1anUtbW9uZ29kYoIIYW55dGhpbmeC 210 NGNvbnRyb2xsZXItc2VydmljZS5jb250cm9sbGVyLW1pY3JvazhzLWxvY2FsaG9z 211 dC5zdmMwCgYIKoZIzj0EAwIDRwAwRAIgDiRHSIxUmxr+LE+Ja9LENbgv/QmC7XFD 212 kBzDYg/oNisCIAx2LGL0r19fcn1rrVEMUrSMI4Dy3tJ0UEVgSbYhBGBA 213 -----END CERTIFICATE-----`, 214 result: false, 215 }, 216 } 217 218 for _, test := range tests { 219 ok, err := pki.IsPemCA([]byte(test.pemStr)) 220 c.Assert(err, jc.ErrorIsNil) 221 c.Assert(ok, gc.Equals, test.result) 222 } 223 }