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  }