github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/tls/resource_locally_signed_cert_test.go (about)

     1  package tls
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/x509"
     6  	"encoding/pem"
     7  	"errors"
     8  	"fmt"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  
    13  	r "github.com/hashicorp/terraform/helper/resource"
    14  	"github.com/hashicorp/terraform/terraform"
    15  )
    16  
    17  func TestLocallySignedCert(t *testing.T) {
    18  	r.Test(t, r.TestCase{
    19  		Providers: testProviders,
    20  		Steps: []r.TestStep{
    21  			r.TestStep{
    22  				Config: fmt.Sprintf(`
    23                      resource "tls_locally_signed_cert" "test" {
    24                          cert_request_pem = <<EOT
    25  %s
    26  EOT
    27  
    28                          validity_period_hours = 1
    29  
    30                          allowed_uses = [
    31                              "key_encipherment",
    32                              "digital_signature",
    33                              "server_auth",
    34                              "client_auth",
    35                          ]
    36  
    37                          ca_key_algorithm = "RSA"
    38                          ca_cert_pem = <<EOT
    39  %s
    40  EOT
    41                          ca_private_key_pem = <<EOT
    42  %s
    43  EOT
    44                      }
    45                      output "cert_pem" {
    46                          value = "${tls_locally_signed_cert.test.cert_pem}"
    47                      }
    48                  `, testCertRequest, testCACert, testCAPrivateKey),
    49  				Check: func(s *terraform.State) error {
    50  					gotUntyped := s.RootModule().Outputs["cert_pem"].Value
    51  					got, ok := gotUntyped.(string)
    52  					if !ok {
    53  						return fmt.Errorf("output for \"cert_pem\" is not a string")
    54  					}
    55  					if !strings.HasPrefix(got, "-----BEGIN CERTIFICATE----") {
    56  						return fmt.Errorf("key is missing cert PEM preamble")
    57  					}
    58  					block, _ := pem.Decode([]byte(got))
    59  					cert, err := x509.ParseCertificate(block.Bytes)
    60  					if err != nil {
    61  						return fmt.Errorf("error parsing cert: %s", err)
    62  					}
    63  					if expected, got := "2", cert.Subject.SerialNumber; got != expected {
    64  						return fmt.Errorf("incorrect subject serial number: expected %v, got %v", expected, got)
    65  					}
    66  					if expected, got := "example.com", cert.Subject.CommonName; got != expected {
    67  						return fmt.Errorf("incorrect subject common name: expected %v, got %v", expected, got)
    68  					}
    69  					if expected, got := "Example, Inc", cert.Subject.Organization[0]; got != expected {
    70  						return fmt.Errorf("incorrect subject organization: expected %v, got %v", expected, got)
    71  					}
    72  					if expected, got := "Department of Terraform Testing", cert.Subject.OrganizationalUnit[0]; got != expected {
    73  						return fmt.Errorf("incorrect subject organizational unit: expected %v, got %v", expected, got)
    74  					}
    75  					if expected, got := "5879 Cotton Link", cert.Subject.StreetAddress[0]; got != expected {
    76  						return fmt.Errorf("incorrect subject street address: expected %v, got %v", expected, got)
    77  					}
    78  					if expected, got := "Pirate Harbor", cert.Subject.Locality[0]; got != expected {
    79  						return fmt.Errorf("incorrect subject locality: expected %v, got %v", expected, got)
    80  					}
    81  					if expected, got := "CA", cert.Subject.Province[0]; got != expected {
    82  						return fmt.Errorf("incorrect subject province: expected %v, got %v", expected, got)
    83  					}
    84  					if expected, got := "US", cert.Subject.Country[0]; got != expected {
    85  						return fmt.Errorf("incorrect subject country: expected %v, got %v", expected, got)
    86  					}
    87  					if expected, got := "95559-1227", cert.Subject.PostalCode[0]; got != expected {
    88  						return fmt.Errorf("incorrect subject postal code: expected %v, got %v", expected, got)
    89  					}
    90  
    91  					if expected, got := 2, len(cert.DNSNames); got != expected {
    92  						return fmt.Errorf("incorrect number of DNS names: expected %v, got %v", expected, got)
    93  					}
    94  					if expected, got := "example.com", cert.DNSNames[0]; got != expected {
    95  						return fmt.Errorf("incorrect DNS name 0: expected %v, got %v", expected, got)
    96  					}
    97  					if expected, got := "example.net", cert.DNSNames[1]; got != expected {
    98  						return fmt.Errorf("incorrect DNS name 0: expected %v, got %v", expected, got)
    99  					}
   100  
   101  					if expected, got := 2, len(cert.IPAddresses); got != expected {
   102  						return fmt.Errorf("incorrect number of IP addresses: expected %v, got %v", expected, got)
   103  					}
   104  					if expected, got := "127.0.0.1", cert.IPAddresses[0].String(); got != expected {
   105  						return fmt.Errorf("incorrect IP address 0: expected %v, got %v", expected, got)
   106  					}
   107  					if expected, got := "127.0.0.2", cert.IPAddresses[1].String(); got != expected {
   108  						return fmt.Errorf("incorrect IP address 0: expected %v, got %v", expected, got)
   109  					}
   110  
   111  					if expected, got := []byte{50, 174, 195, 33, 77, 223, 57, 1, 58, 166, 246, 243, 114, 109, 59, 64, 111, 9, 198, 144}, cert.AuthorityKeyId; !bytes.Equal(got, expected) {
   112  						return fmt.Errorf("incorrect AuthorityKeyId: expected %v, got %v", expected, got)
   113  					}
   114  
   115  					if expected, got := 2, len(cert.ExtKeyUsage); got != expected {
   116  						return fmt.Errorf("incorrect number of ExtKeyUsage: expected %v, got %v", expected, got)
   117  					}
   118  					if expected, got := x509.ExtKeyUsageServerAuth, cert.ExtKeyUsage[0]; got != expected {
   119  						return fmt.Errorf("incorrect ExtKeyUsage[0]: expected %v, got %v", expected, got)
   120  					}
   121  					if expected, got := x509.ExtKeyUsageClientAuth, cert.ExtKeyUsage[1]; got != expected {
   122  						return fmt.Errorf("incorrect ExtKeyUsage[1]: expected %v, got %v", expected, got)
   123  					}
   124  
   125  					if expected, got := x509.KeyUsageKeyEncipherment|x509.KeyUsageDigitalSignature, cert.KeyUsage; got != expected {
   126  						return fmt.Errorf("incorrect KeyUsage: expected %v, got %v", expected, got)
   127  					}
   128  
   129  					// This time checking is a bit sloppy to avoid inconsistent test results
   130  					// depending on the power of the machine running the tests.
   131  					now := time.Now()
   132  					if cert.NotBefore.After(now) {
   133  						return fmt.Errorf("certificate validity begins in the future")
   134  					}
   135  					if now.Sub(cert.NotBefore) > (2 * time.Minute) {
   136  						return fmt.Errorf("certificate validity begins more than two minutes in the past")
   137  					}
   138  					if cert.NotAfter.Sub(cert.NotBefore) != time.Hour {
   139  						return fmt.Errorf("certificate validity is not one hour")
   140  					}
   141  
   142  					caBlock, _ := pem.Decode([]byte(testCACert))
   143  					caCert, err := x509.ParseCertificate(caBlock.Bytes)
   144  					if err != nil {
   145  						return fmt.Errorf("error parsing ca cert: %s", err)
   146  					}
   147  					certPool := x509.NewCertPool()
   148  
   149  					// Verify certificate
   150  					_, err = cert.Verify(x509.VerifyOptions{Roots: certPool})
   151  					if err == nil {
   152  						return errors.New("incorrectly verified certificate")
   153  					} else if _, ok := err.(x509.UnknownAuthorityError); !ok {
   154  						return fmt.Errorf("incorrect verify error: expected UnknownAuthorityError, got %v", err)
   155  					}
   156  					certPool.AddCert(caCert)
   157  					if _, err = cert.Verify(x509.VerifyOptions{Roots: certPool}); err != nil {
   158  						return fmt.Errorf("verify failed: %s", err)
   159  					}
   160  
   161  					return nil
   162  				},
   163  			},
   164  		},
   165  	})
   166  }