1package cert 2 3import ( 4 "context" 5 "crypto/ecdsa" 6 "crypto/elliptic" 7 "crypto/rand" 8 "encoding/pem" 9 mathrand "math/rand" 10 "net/http" 11 "net/url" 12 "path/filepath" 13 14 "github.com/go-test/deep" 15 "github.com/hashicorp/go-sockaddr" 16 17 "golang.org/x/net/http2" 18 19 "crypto/rsa" 20 "crypto/tls" 21 "crypto/x509" 22 "crypto/x509/pkix" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "math/big" 27 "net" 28 "os" 29 "reflect" 30 "testing" 31 "time" 32 33 cleanhttp "github.com/hashicorp/go-cleanhttp" 34 log "github.com/hashicorp/go-hclog" 35 "github.com/hashicorp/vault/api" 36 vaulthttp "github.com/hashicorp/vault/http" 37 38 rootcerts "github.com/hashicorp/go-rootcerts" 39 "github.com/hashicorp/vault/builtin/logical/pki" 40 logicaltest "github.com/hashicorp/vault/helper/testhelpers/logical" 41 "github.com/hashicorp/vault/sdk/framework" 42 "github.com/hashicorp/vault/sdk/helper/certutil" 43 "github.com/hashicorp/vault/sdk/helper/tokenutil" 44 "github.com/hashicorp/vault/sdk/logical" 45 "github.com/hashicorp/vault/vault" 46 "github.com/mitchellh/mapstructure" 47) 48 49const ( 50 serverCertPath = "test-fixtures/cacert.pem" 51 serverKeyPath = "test-fixtures/cakey.pem" 52 serverCAPath = serverCertPath 53 54 testRootCACertPath1 = "test-fixtures/testcacert1.pem" 55 testRootCAKeyPath1 = "test-fixtures/testcakey1.pem" 56 testCertPath1 = "test-fixtures/testissuedcert4.pem" 57 testKeyPath1 = "test-fixtures/testissuedkey4.pem" 58 testIssuedCertCRL = "test-fixtures/issuedcertcrl" 59 60 testRootCACertPath2 = "test-fixtures/testcacert2.pem" 61 testRootCAKeyPath2 = "test-fixtures/testcakey2.pem" 62 testRootCertCRL = "test-fixtures/cacert2crl" 63) 64 65func generateTestCertAndConnState(t *testing.T, template *x509.Certificate) (string, tls.ConnectionState, error) { 66 t.Helper() 67 tempDir, err := ioutil.TempDir("", "vault-cert-auth-test-") 68 if err != nil { 69 t.Fatal(err) 70 } 71 t.Logf("test %s, temp dir %s", t.Name(), tempDir) 72 caCertTemplate := &x509.Certificate{ 73 Subject: pkix.Name{ 74 CommonName: "localhost", 75 }, 76 DNSNames: []string{"localhost"}, 77 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 78 KeyUsage: x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign), 79 SerialNumber: big.NewInt(mathrand.Int63()), 80 NotBefore: time.Now().Add(-30 * time.Second), 81 NotAfter: time.Now().Add(262980 * time.Hour), 82 BasicConstraintsValid: true, 83 IsCA: true, 84 } 85 caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 86 if err != nil { 87 t.Fatal(err) 88 } 89 caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey) 90 if err != nil { 91 t.Fatal(err) 92 } 93 caCert, err := x509.ParseCertificate(caBytes) 94 if err != nil { 95 t.Fatal(err) 96 } 97 caCertPEMBlock := &pem.Block{ 98 Type: "CERTIFICATE", 99 Bytes: caBytes, 100 } 101 err = ioutil.WriteFile(filepath.Join(tempDir, "ca_cert.pem"), pem.EncodeToMemory(caCertPEMBlock), 0755) 102 if err != nil { 103 t.Fatal(err) 104 } 105 marshaledCAKey, err := x509.MarshalECPrivateKey(caKey) 106 if err != nil { 107 t.Fatal(err) 108 } 109 caKeyPEMBlock := &pem.Block{ 110 Type: "EC PRIVATE KEY", 111 Bytes: marshaledCAKey, 112 } 113 err = ioutil.WriteFile(filepath.Join(tempDir, "ca_key.pem"), pem.EncodeToMemory(caKeyPEMBlock), 0755) 114 if err != nil { 115 t.Fatal(err) 116 } 117 118 key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 119 if err != nil { 120 t.Fatal(err) 121 } 122 certBytes, err := x509.CreateCertificate(rand.Reader, template, caCert, key.Public(), caKey) 123 if err != nil { 124 t.Fatal(err) 125 } 126 certPEMBlock := &pem.Block{ 127 Type: "CERTIFICATE", 128 Bytes: certBytes, 129 } 130 err = ioutil.WriteFile(filepath.Join(tempDir, "cert.pem"), pem.EncodeToMemory(certPEMBlock), 0755) 131 if err != nil { 132 t.Fatal(err) 133 } 134 marshaledKey, err := x509.MarshalECPrivateKey(key) 135 if err != nil { 136 t.Fatal(err) 137 } 138 keyPEMBlock := &pem.Block{ 139 Type: "EC PRIVATE KEY", 140 Bytes: marshaledKey, 141 } 142 err = ioutil.WriteFile(filepath.Join(tempDir, "key.pem"), pem.EncodeToMemory(keyPEMBlock), 0755) 143 if err != nil { 144 t.Fatal(err) 145 } 146 connInfo, err := testConnState(filepath.Join(tempDir, "cert.pem"), filepath.Join(tempDir, "key.pem"), filepath.Join(tempDir, "ca_cert.pem")) 147 return tempDir, connInfo, err 148} 149 150// Unlike testConnState, this method does not use the same 'tls.Config' objects for 151// both dialing and listening. Instead, it runs the server without specifying its CA. 152// But the client, presents the CA cert of the server to trust the server. 153// The client can present a cert and key which is completely independent of server's CA. 154// The connection state returned will contain the certificate presented by the client. 155func connectionState(serverCAPath, serverCertPath, serverKeyPath, clientCertPath, clientKeyPath string) (tls.ConnectionState, error) { 156 serverKeyPair, err := tls.LoadX509KeyPair(serverCertPath, serverKeyPath) 157 if err != nil { 158 return tls.ConnectionState{}, err 159 } 160 // Prepare the listener configuration with server's key pair 161 listenConf := &tls.Config{ 162 Certificates: []tls.Certificate{serverKeyPair}, 163 ClientAuth: tls.RequestClientCert, 164 } 165 166 clientKeyPair, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath) 167 if err != nil { 168 return tls.ConnectionState{}, err 169 } 170 // Load the CA cert required by the client to authenticate the server. 171 rootConfig := &rootcerts.Config{ 172 CAFile: serverCAPath, 173 } 174 serverCAs, err := rootcerts.LoadCACerts(rootConfig) 175 if err != nil { 176 return tls.ConnectionState{}, err 177 } 178 // Prepare the dial configuration that the client uses to establish the connection. 179 dialConf := &tls.Config{ 180 Certificates: []tls.Certificate{clientKeyPair}, 181 RootCAs: serverCAs, 182 } 183 184 // Start the server. 185 list, err := tls.Listen("tcp", "127.0.0.1:0", listenConf) 186 if err != nil { 187 return tls.ConnectionState{}, err 188 } 189 defer list.Close() 190 191 // Accept connections. 192 serverErrors := make(chan error, 1) 193 connState := make(chan tls.ConnectionState) 194 go func() { 195 defer close(connState) 196 serverConn, err := list.Accept() 197 if err != nil { 198 serverErrors <- err 199 close(serverErrors) 200 return 201 } 202 defer serverConn.Close() 203 204 // Read the ping 205 buf := make([]byte, 4) 206 _, err = serverConn.Read(buf) 207 if (err != nil) && (err != io.EOF) { 208 serverErrors <- err 209 close(serverErrors) 210 return 211 } 212 close(serverErrors) 213 connState <- serverConn.(*tls.Conn).ConnectionState() 214 }() 215 216 // Establish a connection from the client side and write a few bytes. 217 clientErrors := make(chan error, 1) 218 go func() { 219 addr := list.Addr().String() 220 conn, err := tls.Dial("tcp", addr, dialConf) 221 if err != nil { 222 clientErrors <- err 223 close(clientErrors) 224 return 225 } 226 defer conn.Close() 227 228 // Write ping 229 _, err = conn.Write([]byte("ping")) 230 if err != nil { 231 clientErrors <- err 232 } 233 close(clientErrors) 234 }() 235 236 for err = range clientErrors { 237 if err != nil { 238 return tls.ConnectionState{}, fmt.Errorf("error in client goroutine:%v", err) 239 } 240 } 241 242 for err = range serverErrors { 243 if err != nil { 244 return tls.ConnectionState{}, fmt.Errorf("error in server goroutine:%v", err) 245 } 246 } 247 // Grab the current state 248 return <-connState, nil 249} 250 251func TestBackend_PermittedDNSDomainsIntermediateCA(t *testing.T) { 252 // Enable PKI secret engine and Cert auth method 253 coreConfig := &vault.CoreConfig{ 254 DisableMlock: true, 255 DisableCache: true, 256 Logger: log.NewNullLogger(), 257 CredentialBackends: map[string]logical.Factory{ 258 "cert": Factory, 259 }, 260 LogicalBackends: map[string]logical.Factory{ 261 "pki": pki.Factory, 262 }, 263 } 264 cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ 265 HandlerFunc: vaulthttp.Handler, 266 }) 267 cluster.Start() 268 defer cluster.Cleanup() 269 cores := cluster.Cores 270 vault.TestWaitActive(t, cores[0].Core) 271 client := cores[0].Client 272 273 var err error 274 275 // Mount /pki as a root CA 276 err = client.Sys().Mount("pki", &api.MountInput{ 277 Type: "pki", 278 Config: api.MountConfigInput{ 279 DefaultLeaseTTL: "16h", 280 MaxLeaseTTL: "32h", 281 }, 282 }) 283 if err != nil { 284 t.Fatal(err) 285 } 286 287 // Set the cluster's certificate as the root CA in /pki 288 pemBundleRootCA := string(cluster.CACertPEM) + string(cluster.CAKeyPEM) 289 _, err = client.Logical().Write("pki/config/ca", map[string]interface{}{ 290 "pem_bundle": pemBundleRootCA, 291 }) 292 if err != nil { 293 t.Fatal(err) 294 } 295 296 // Mount /pki2 to operate as an intermediate CA 297 err = client.Sys().Mount("pki2", &api.MountInput{ 298 Type: "pki", 299 Config: api.MountConfigInput{ 300 DefaultLeaseTTL: "16h", 301 MaxLeaseTTL: "32h", 302 }, 303 }) 304 if err != nil { 305 t.Fatal(err) 306 } 307 308 // Create a CSR for the intermediate CA 309 secret, err := client.Logical().Write("pki2/intermediate/generate/internal", nil) 310 if err != nil { 311 t.Fatal(err) 312 } 313 intermediateCSR := secret.Data["csr"].(string) 314 315 // Sign the intermediate CSR using /pki 316 secret, err = client.Logical().Write("pki/root/sign-intermediate", map[string]interface{}{ 317 "permitted_dns_domains": ".myvault.com", 318 "csr": intermediateCSR, 319 }) 320 if err != nil { 321 t.Fatal(err) 322 } 323 intermediateCertPEM := secret.Data["certificate"].(string) 324 325 // Configure the intermediate cert as the CA in /pki2 326 _, err = client.Logical().Write("pki2/intermediate/set-signed", map[string]interface{}{ 327 "certificate": intermediateCertPEM, 328 }) 329 if err != nil { 330 t.Fatal(err) 331 } 332 333 // Create a role on the intermediate CA mount 334 _, err = client.Logical().Write("pki2/roles/myvault-dot-com", map[string]interface{}{ 335 "allowed_domains": "myvault.com", 336 "allow_subdomains": "true", 337 "max_ttl": "5m", 338 }) 339 if err != nil { 340 t.Fatal(err) 341 } 342 343 // Issue a leaf cert using the intermediate CA 344 secret, err = client.Logical().Write("pki2/issue/myvault-dot-com", map[string]interface{}{ 345 "common_name": "cert.myvault.com", 346 "format": "pem", 347 "ip_sans": "127.0.0.1", 348 }) 349 if err != nil { 350 t.Fatal(err) 351 } 352 leafCertPEM := secret.Data["certificate"].(string) 353 leafCertKeyPEM := secret.Data["private_key"].(string) 354 355 // Enable the cert auth method 356 err = client.Sys().EnableAuthWithOptions("cert", &api.EnableAuthOptions{ 357 Type: "cert", 358 }) 359 if err != nil { 360 t.Fatal(err) 361 } 362 363 // Set the intermediate CA cert as a trusted certificate in the backend 364 _, err = client.Logical().Write("auth/cert/certs/myvault-dot-com", map[string]interface{}{ 365 "display_name": "myvault.com", 366 "policies": "default", 367 "certificate": intermediateCertPEM, 368 }) 369 if err != nil { 370 t.Fatal(err) 371 } 372 373 // Create temporary files for CA cert, client cert and client cert key. 374 // This is used to configure TLS in the api client. 375 caCertFile, err := ioutil.TempFile("", "caCert") 376 if err != nil { 377 t.Fatal(err) 378 } 379 defer os.Remove(caCertFile.Name()) 380 if _, err := caCertFile.Write([]byte(cluster.CACertPEM)); err != nil { 381 t.Fatal(err) 382 } 383 if err := caCertFile.Close(); err != nil { 384 t.Fatal(err) 385 } 386 387 leafCertFile, err := ioutil.TempFile("", "leafCert") 388 if err != nil { 389 t.Fatal(err) 390 } 391 defer os.Remove(leafCertFile.Name()) 392 if _, err := leafCertFile.Write([]byte(leafCertPEM)); err != nil { 393 t.Fatal(err) 394 } 395 if err := leafCertFile.Close(); err != nil { 396 t.Fatal(err) 397 } 398 399 leafCertKeyFile, err := ioutil.TempFile("", "leafCertKey") 400 if err != nil { 401 t.Fatal(err) 402 } 403 defer os.Remove(leafCertKeyFile.Name()) 404 if _, err := leafCertKeyFile.Write([]byte(leafCertKeyPEM)); err != nil { 405 t.Fatal(err) 406 } 407 if err := leafCertKeyFile.Close(); err != nil { 408 t.Fatal(err) 409 } 410 411 // This function is a copy-pasta from the NewTestCluster, with the 412 // modification to reconfigure the TLS on the api client with the leaf 413 // certificate generated above. 414 getAPIClient := func(port int, tlsConfig *tls.Config) *api.Client { 415 transport := cleanhttp.DefaultPooledTransport() 416 transport.TLSClientConfig = tlsConfig.Clone() 417 if err := http2.ConfigureTransport(transport); err != nil { 418 t.Fatal(err) 419 } 420 client := &http.Client{ 421 Transport: transport, 422 CheckRedirect: func(*http.Request, []*http.Request) error { 423 // This can of course be overridden per-test by using its own client 424 return fmt.Errorf("redirects not allowed in these tests") 425 }, 426 } 427 config := api.DefaultConfig() 428 if config.Error != nil { 429 t.Fatal(config.Error) 430 } 431 config.Address = fmt.Sprintf("https://127.0.0.1:%d", port) 432 config.HttpClient = client 433 434 // Set the above issued certificates as the client certificates 435 config.ConfigureTLS(&api.TLSConfig{ 436 CACert: caCertFile.Name(), 437 ClientCert: leafCertFile.Name(), 438 ClientKey: leafCertKeyFile.Name(), 439 }) 440 441 apiClient, err := api.NewClient(config) 442 if err != nil { 443 t.Fatal(err) 444 } 445 return apiClient 446 } 447 448 // Create a new api client with the desired TLS configuration 449 newClient := getAPIClient(cores[0].Listeners[0].Address.Port, cores[0].TLSConfig) 450 451 secret, err = newClient.Logical().Write("auth/cert/login", map[string]interface{}{ 452 "name": "myvault-dot-com", 453 }) 454 if err != nil { 455 t.Fatal(err) 456 } 457 if secret.Auth == nil || secret.Auth.ClientToken == "" { 458 t.Fatalf("expected a successful authentication") 459 } 460} 461 462func TestBackend_NonCAExpiry(t *testing.T) { 463 var resp *logical.Response 464 var err error 465 466 // Create a self-signed certificate and issue a leaf certificate using the 467 // CA cert 468 template := &x509.Certificate{ 469 SerialNumber: big.NewInt(1234), 470 Subject: pkix.Name{ 471 CommonName: "localhost", 472 Organization: []string{"hashicorp"}, 473 OrganizationalUnit: []string{"vault"}, 474 }, 475 BasicConstraintsValid: true, 476 NotBefore: time.Now().Add(-30 * time.Second), 477 NotAfter: time.Now().Add(50 * time.Second), 478 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, 479 KeyUsage: x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign), 480 } 481 482 // Set IP SAN 483 parsedIP := net.ParseIP("127.0.0.1") 484 if parsedIP == nil { 485 t.Fatalf("failed to create parsed IP") 486 } 487 template.IPAddresses = []net.IP{parsedIP} 488 489 // Private key for CA cert 490 caPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) 491 if err != nil { 492 t.Fatal(err) 493 } 494 495 // Marshalling to be able to create PEM file 496 caPrivateKeyBytes := x509.MarshalPKCS1PrivateKey(caPrivateKey) 497 498 caPublicKey := &caPrivateKey.PublicKey 499 500 template.IsCA = true 501 502 caCertBytes, err := x509.CreateCertificate(rand.Reader, template, template, caPublicKey, caPrivateKey) 503 if err != nil { 504 t.Fatal(err) 505 } 506 507 caCert, err := x509.ParseCertificate(caCertBytes) 508 if err != nil { 509 t.Fatal(err) 510 } 511 512 parsedCaBundle := &certutil.ParsedCertBundle{ 513 Certificate: caCert, 514 CertificateBytes: caCertBytes, 515 PrivateKeyBytes: caPrivateKeyBytes, 516 PrivateKeyType: certutil.RSAPrivateKey, 517 } 518 519 caCertBundle, err := parsedCaBundle.ToCertBundle() 520 if err != nil { 521 t.Fatal(err) 522 } 523 524 caCertFile, err := ioutil.TempFile("", "caCert") 525 if err != nil { 526 t.Fatal(err) 527 } 528 529 defer os.Remove(caCertFile.Name()) 530 531 if _, err := caCertFile.Write([]byte(caCertBundle.Certificate)); err != nil { 532 t.Fatal(err) 533 } 534 if err := caCertFile.Close(); err != nil { 535 t.Fatal(err) 536 } 537 538 caKeyFile, err := ioutil.TempFile("", "caKey") 539 if err != nil { 540 t.Fatal(err) 541 } 542 543 defer os.Remove(caKeyFile.Name()) 544 545 if _, err := caKeyFile.Write([]byte(caCertBundle.PrivateKey)); err != nil { 546 t.Fatal(err) 547 } 548 if err := caKeyFile.Close(); err != nil { 549 t.Fatal(err) 550 } 551 552 // Prepare template for non-CA cert 553 554 template.IsCA = false 555 template.SerialNumber = big.NewInt(5678) 556 557 template.KeyUsage = x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign) 558 issuedPrivateKey, err := rsa.GenerateKey(rand.Reader, 2048) 559 if err != nil { 560 t.Fatal(err) 561 } 562 563 issuedPrivateKeyBytes := x509.MarshalPKCS1PrivateKey(issuedPrivateKey) 564 565 issuedPublicKey := &issuedPrivateKey.PublicKey 566 567 // Keep a short certificate lifetime so logins can be tested both when 568 // cert is valid and when it gets expired 569 template.NotBefore = time.Now().Add(-2 * time.Second) 570 template.NotAfter = time.Now().Add(3 * time.Second) 571 572 issuedCertBytes, err := x509.CreateCertificate(rand.Reader, template, caCert, issuedPublicKey, caPrivateKey) 573 if err != nil { 574 t.Fatal(err) 575 } 576 577 issuedCert, err := x509.ParseCertificate(issuedCertBytes) 578 if err != nil { 579 t.Fatal(err) 580 } 581 582 parsedIssuedBundle := &certutil.ParsedCertBundle{ 583 Certificate: issuedCert, 584 CertificateBytes: issuedCertBytes, 585 PrivateKeyBytes: issuedPrivateKeyBytes, 586 PrivateKeyType: certutil.RSAPrivateKey, 587 } 588 589 issuedCertBundle, err := parsedIssuedBundle.ToCertBundle() 590 if err != nil { 591 t.Fatal(err) 592 } 593 594 issuedCertFile, err := ioutil.TempFile("", "issuedCert") 595 if err != nil { 596 t.Fatal(err) 597 } 598 599 defer os.Remove(issuedCertFile.Name()) 600 601 if _, err := issuedCertFile.Write([]byte(issuedCertBundle.Certificate)); err != nil { 602 t.Fatal(err) 603 } 604 if err := issuedCertFile.Close(); err != nil { 605 t.Fatal(err) 606 } 607 608 issuedKeyFile, err := ioutil.TempFile("", "issuedKey") 609 if err != nil { 610 t.Fatal(err) 611 } 612 613 defer os.Remove(issuedKeyFile.Name()) 614 615 if _, err := issuedKeyFile.Write([]byte(issuedCertBundle.PrivateKey)); err != nil { 616 t.Fatal(err) 617 } 618 if err := issuedKeyFile.Close(); err != nil { 619 t.Fatal(err) 620 } 621 622 config := logical.TestBackendConfig() 623 storage := &logical.InmemStorage{} 624 config.StorageView = storage 625 626 b, err := Factory(context.Background(), config) 627 if err != nil { 628 t.Fatal(err) 629 } 630 631 // Register the Non-CA certificate of the client key pair 632 certData := map[string]interface{}{ 633 "certificate": issuedCertBundle.Certificate, 634 "policies": "abc", 635 "display_name": "cert1", 636 "ttl": 10000, 637 } 638 certReq := &logical.Request{ 639 Operation: logical.UpdateOperation, 640 Path: "certs/cert1", 641 Storage: storage, 642 Data: certData, 643 } 644 645 resp, err = b.HandleRequest(context.Background(), certReq) 646 if err != nil || (resp != nil && resp.IsError()) { 647 t.Fatalf("err:%v resp:%#v", err, resp) 648 } 649 650 // Create connection state using the certificates generated 651 connState, err := connectionState(caCertFile.Name(), caCertFile.Name(), caKeyFile.Name(), issuedCertFile.Name(), issuedKeyFile.Name()) 652 if err != nil { 653 t.Fatalf("error testing connection state:%v", err) 654 } 655 656 loginReq := &logical.Request{ 657 Operation: logical.UpdateOperation, 658 Storage: storage, 659 Path: "login", 660 Connection: &logical.Connection{ 661 ConnState: &connState, 662 }, 663 } 664 665 // Login when the certificate is still valid. Login should succeed. 666 resp, err = b.HandleRequest(context.Background(), loginReq) 667 if err != nil || (resp != nil && resp.IsError()) { 668 t.Fatalf("err:%v resp:%#v", err, resp) 669 } 670 671 // Wait until the certificate expires 672 time.Sleep(5 * time.Second) 673 674 // Login attempt after certificate expiry should fail 675 resp, err = b.HandleRequest(context.Background(), loginReq) 676 if err == nil { 677 t.Fatalf("expected error due to expired certificate") 678 } 679} 680 681func TestBackend_RegisteredNonCA_CRL(t *testing.T) { 682 config := logical.TestBackendConfig() 683 storage := &logical.InmemStorage{} 684 config.StorageView = storage 685 686 b, err := Factory(context.Background(), config) 687 if err != nil { 688 t.Fatal(err) 689 } 690 691 nonCACert, err := ioutil.ReadFile(testCertPath1) 692 if err != nil { 693 t.Fatal(err) 694 } 695 696 // Register the Non-CA certificate of the client key pair 697 certData := map[string]interface{}{ 698 "certificate": nonCACert, 699 "policies": "abc", 700 "display_name": "cert1", 701 "ttl": 10000, 702 } 703 certReq := &logical.Request{ 704 Operation: logical.UpdateOperation, 705 Path: "certs/cert1", 706 Storage: storage, 707 Data: certData, 708 } 709 710 resp, err := b.HandleRequest(context.Background(), certReq) 711 if err != nil || (resp != nil && resp.IsError()) { 712 t.Fatalf("err:%v resp:%#v", err, resp) 713 } 714 715 // Connection state is presenting the client Non-CA cert and its key. 716 // This is exactly what is registered at the backend. 717 connState, err := connectionState(serverCAPath, serverCertPath, serverKeyPath, testCertPath1, testKeyPath1) 718 if err != nil { 719 t.Fatalf("error testing connection state:%v", err) 720 } 721 loginReq := &logical.Request{ 722 Operation: logical.UpdateOperation, 723 Storage: storage, 724 Path: "login", 725 Connection: &logical.Connection{ 726 ConnState: &connState, 727 }, 728 } 729 // Login should succeed. 730 resp, err = b.HandleRequest(context.Background(), loginReq) 731 if err != nil || (resp != nil && resp.IsError()) { 732 t.Fatalf("err:%v resp:%#v", err, resp) 733 } 734 735 // Register a CRL containing the issued client certificate used above. 736 issuedCRL, err := ioutil.ReadFile(testIssuedCertCRL) 737 if err != nil { 738 t.Fatal(err) 739 } 740 crlData := map[string]interface{}{ 741 "crl": issuedCRL, 742 } 743 crlReq := &logical.Request{ 744 Operation: logical.UpdateOperation, 745 Storage: storage, 746 Path: "crls/issuedcrl", 747 Data: crlData, 748 } 749 resp, err = b.HandleRequest(context.Background(), crlReq) 750 if err != nil || (resp != nil && resp.IsError()) { 751 t.Fatalf("err:%v resp:%#v", err, resp) 752 } 753 754 // Attempt login with the same connection state but with the CRL registered 755 resp, err = b.HandleRequest(context.Background(), loginReq) 756 if err != nil { 757 t.Fatal(err) 758 } 759 if resp == nil || !resp.IsError() { 760 t.Fatalf("expected failure due to revoked certificate") 761 } 762} 763 764func TestBackend_CRLs(t *testing.T) { 765 config := logical.TestBackendConfig() 766 storage := &logical.InmemStorage{} 767 config.StorageView = storage 768 769 b, err := Factory(context.Background(), config) 770 if err != nil { 771 t.Fatal(err) 772 } 773 774 clientCA1, err := ioutil.ReadFile(testRootCACertPath1) 775 if err != nil { 776 t.Fatal(err) 777 } 778 // Register the CA certificate of the client key pair 779 certData := map[string]interface{}{ 780 "certificate": clientCA1, 781 "policies": "abc", 782 "display_name": "cert1", 783 "ttl": 10000, 784 } 785 786 certReq := &logical.Request{ 787 Operation: logical.UpdateOperation, 788 Path: "certs/cert1", 789 Storage: storage, 790 Data: certData, 791 } 792 793 resp, err := b.HandleRequest(context.Background(), certReq) 794 if err != nil || (resp != nil && resp.IsError()) { 795 t.Fatalf("err:%v resp:%#v", err, resp) 796 } 797 798 // Connection state is presenting the client CA cert and its key. 799 // This is exactly what is registered at the backend. 800 connState, err := connectionState(serverCAPath, serverCertPath, serverKeyPath, testRootCACertPath1, testRootCAKeyPath1) 801 if err != nil { 802 t.Fatalf("error testing connection state:%v", err) 803 } 804 loginReq := &logical.Request{ 805 Operation: logical.UpdateOperation, 806 Storage: storage, 807 Path: "login", 808 Connection: &logical.Connection{ 809 ConnState: &connState, 810 }, 811 } 812 resp, err = b.HandleRequest(context.Background(), loginReq) 813 if err != nil || (resp != nil && resp.IsError()) { 814 t.Fatalf("err:%v resp:%#v", err, resp) 815 } 816 817 // Now, without changing the registered client CA cert, present from 818 // the client side, a cert issued using the registered CA. 819 connState, err = connectionState(serverCAPath, serverCertPath, serverKeyPath, testCertPath1, testKeyPath1) 820 if err != nil { 821 t.Fatalf("error testing connection state: %v", err) 822 } 823 loginReq.Connection.ConnState = &connState 824 825 // Attempt login with the updated connection 826 resp, err = b.HandleRequest(context.Background(), loginReq) 827 if err != nil || (resp != nil && resp.IsError()) { 828 t.Fatalf("err:%v resp:%#v", err, resp) 829 } 830 831 // Register a CRL containing the issued client certificate used above. 832 issuedCRL, err := ioutil.ReadFile(testIssuedCertCRL) 833 if err != nil { 834 t.Fatal(err) 835 } 836 crlData := map[string]interface{}{ 837 "crl": issuedCRL, 838 } 839 840 crlReq := &logical.Request{ 841 Operation: logical.UpdateOperation, 842 Storage: storage, 843 Path: "crls/issuedcrl", 844 Data: crlData, 845 } 846 resp, err = b.HandleRequest(context.Background(), crlReq) 847 if err != nil || (resp != nil && resp.IsError()) { 848 t.Fatalf("err:%v resp:%#v", err, resp) 849 } 850 851 // Attempt login with the revoked certificate. 852 resp, err = b.HandleRequest(context.Background(), loginReq) 853 if err != nil { 854 t.Fatal(err) 855 } 856 if resp == nil || !resp.IsError() { 857 t.Fatalf("expected failure due to revoked certificate") 858 } 859 860 // Register a different client CA certificate. 861 clientCA2, err := ioutil.ReadFile(testRootCACertPath2) 862 if err != nil { 863 t.Fatal(err) 864 } 865 certData["certificate"] = clientCA2 866 resp, err = b.HandleRequest(context.Background(), certReq) 867 if err != nil || (resp != nil && resp.IsError()) { 868 t.Fatalf("err:%v resp:%#v", err, resp) 869 } 870 871 // Test login using a different client CA cert pair. 872 connState, err = connectionState(serverCAPath, serverCertPath, serverKeyPath, testRootCACertPath2, testRootCAKeyPath2) 873 if err != nil { 874 t.Fatalf("error testing connection state: %v", err) 875 } 876 loginReq.Connection.ConnState = &connState 877 878 // Attempt login with the updated connection 879 resp, err = b.HandleRequest(context.Background(), loginReq) 880 if err != nil || (resp != nil && resp.IsError()) { 881 t.Fatalf("err:%v resp:%#v", err, resp) 882 } 883 884 // Register a CRL containing the root CA certificate used above. 885 rootCRL, err := ioutil.ReadFile(testRootCertCRL) 886 if err != nil { 887 t.Fatal(err) 888 } 889 crlData["crl"] = rootCRL 890 resp, err = b.HandleRequest(context.Background(), crlReq) 891 if err != nil || (resp != nil && resp.IsError()) { 892 t.Fatalf("err:%v resp:%#v", err, resp) 893 } 894 895 // Attempt login with the same connection state but with the CRL registered 896 resp, err = b.HandleRequest(context.Background(), loginReq) 897 if err != nil { 898 t.Fatal(err) 899 } 900 if resp == nil || !resp.IsError() { 901 t.Fatalf("expected failure due to revoked certificate") 902 } 903} 904 905func testFactory(t *testing.T) logical.Backend { 906 b, err := Factory(context.Background(), &logical.BackendConfig{ 907 System: &logical.StaticSystemView{ 908 DefaultLeaseTTLVal: 1000 * time.Second, 909 MaxLeaseTTLVal: 1800 * time.Second, 910 }, 911 StorageView: &logical.InmemStorage{}, 912 }) 913 if err != nil { 914 t.Fatalf("error: %s", err) 915 } 916 return b 917} 918 919// Test the certificates being registered to the backend 920func TestBackend_CertWrites(t *testing.T) { 921 // CA cert 922 ca1, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 923 if err != nil { 924 t.Fatalf("err: %v", err) 925 } 926 // Non CA Cert 927 ca2, err := ioutil.ReadFile("test-fixtures/keys/cert.pem") 928 if err != nil { 929 t.Fatalf("err: %v", err) 930 } 931 // Non CA cert without TLS web client authentication 932 ca3, err := ioutil.ReadFile("test-fixtures/noclientauthcert.pem") 933 if err != nil { 934 t.Fatalf("err: %v", err) 935 } 936 937 tc := logicaltest.TestCase{ 938 CredentialBackend: testFactory(t), 939 Steps: []logicaltest.TestStep{ 940 testAccStepCert(t, "aaa", ca1, "foo", allowed{}, false), 941 testAccStepCert(t, "bbb", ca2, "foo", allowed{}, false), 942 testAccStepCert(t, "ccc", ca3, "foo", allowed{}, true), 943 }, 944 } 945 tc.Steps = append(tc.Steps, testAccStepListCerts(t, []string{"aaa", "bbb"})...) 946 logicaltest.Test(t, tc) 947} 948 949// Test a client trusted by a CA 950func TestBackend_basic_CA(t *testing.T) { 951 connState, err := testConnState("test-fixtures/keys/cert.pem", 952 "test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem") 953 if err != nil { 954 t.Fatalf("error testing connection state: %v", err) 955 } 956 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 957 if err != nil { 958 t.Fatalf("err: %v", err) 959 } 960 logicaltest.Test(t, logicaltest.TestCase{ 961 CredentialBackend: testFactory(t), 962 Steps: []logicaltest.TestStep{ 963 testAccStepCert(t, "web", ca, "foo", allowed{}, false), 964 testAccStepLogin(t, connState), 965 testAccStepCertLease(t, "web", ca, "foo"), 966 testAccStepCertTTL(t, "web", ca, "foo"), 967 testAccStepLogin(t, connState), 968 testAccStepCertMaxTTL(t, "web", ca, "foo"), 969 testAccStepLogin(t, connState), 970 testAccStepCertNoLease(t, "web", ca, "foo"), 971 testAccStepLoginDefaultLease(t, connState), 972 testAccStepCert(t, "web", ca, "foo", allowed{names: "*.example.com"}, false), 973 testAccStepLogin(t, connState), 974 testAccStepCert(t, "web", ca, "foo", allowed{names: "*.invalid.com"}, false), 975 testAccStepLoginInvalid(t, connState), 976 }, 977 }) 978} 979 980// Test CRL behavior 981func TestBackend_Basic_CRLs(t *testing.T) { 982 connState, err := testConnState("test-fixtures/keys/cert.pem", 983 "test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem") 984 if err != nil { 985 t.Fatalf("error testing connection state: %v", err) 986 } 987 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 988 if err != nil { 989 t.Fatalf("err: %v", err) 990 } 991 crl, err := ioutil.ReadFile("test-fixtures/root/root.crl") 992 if err != nil { 993 t.Fatalf("err: %v", err) 994 } 995 logicaltest.Test(t, logicaltest.TestCase{ 996 CredentialBackend: testFactory(t), 997 Steps: []logicaltest.TestStep{ 998 testAccStepCertNoLease(t, "web", ca, "foo"), 999 testAccStepLoginDefaultLease(t, connState), 1000 testAccStepAddCRL(t, crl, connState), 1001 testAccStepReadCRL(t, connState), 1002 testAccStepLoginInvalid(t, connState), 1003 testAccStepDeleteCRL(t, connState), 1004 testAccStepLoginDefaultLease(t, connState), 1005 }, 1006 }) 1007} 1008 1009// Test a self-signed client (root CA) that is trusted 1010func TestBackend_basic_singleCert(t *testing.T) { 1011 connState, err := testConnState("test-fixtures/root/rootcacert.pem", 1012 "test-fixtures/root/rootcakey.pem", "test-fixtures/root/rootcacert.pem") 1013 if err != nil { 1014 t.Fatalf("error testing connection state: %v", err) 1015 } 1016 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 1017 if err != nil { 1018 t.Fatalf("err: %v", err) 1019 } 1020 logicaltest.Test(t, logicaltest.TestCase{ 1021 CredentialBackend: testFactory(t), 1022 Steps: []logicaltest.TestStep{ 1023 testAccStepCert(t, "web", ca, "foo", allowed{}, false), 1024 testAccStepLogin(t, connState), 1025 testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com"}, false), 1026 testAccStepLogin(t, connState), 1027 testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid"}, false), 1028 testAccStepLoginInvalid(t, connState), 1029 testAccStepCert(t, "web", ca, "foo", allowed{ext: "1.2.3.4:invalid"}, false), 1030 testAccStepLoginInvalid(t, connState), 1031 }, 1032 }) 1033} 1034 1035func TestBackend_common_name_singleCert(t *testing.T) { 1036 connState, err := testConnState("test-fixtures/root/rootcacert.pem", 1037 "test-fixtures/root/rootcakey.pem", "test-fixtures/root/rootcacert.pem") 1038 if err != nil { 1039 t.Fatalf("error testing connection state: %v", err) 1040 } 1041 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 1042 if err != nil { 1043 t.Fatalf("err: %v", err) 1044 } 1045 logicaltest.Test(t, logicaltest.TestCase{ 1046 CredentialBackend: testFactory(t), 1047 Steps: []logicaltest.TestStep{ 1048 testAccStepCert(t, "web", ca, "foo", allowed{}, false), 1049 testAccStepLogin(t, connState), 1050 testAccStepCert(t, "web", ca, "foo", allowed{common_names: "example.com"}, false), 1051 testAccStepLogin(t, connState), 1052 testAccStepCert(t, "web", ca, "foo", allowed{common_names: "invalid"}, false), 1053 testAccStepLoginInvalid(t, connState), 1054 testAccStepCert(t, "web", ca, "foo", allowed{ext: "1.2.3.4:invalid"}, false), 1055 testAccStepLoginInvalid(t, connState), 1056 }, 1057 }) 1058} 1059 1060// Test a self-signed client with custom ext (root CA) that is trusted 1061func TestBackend_ext_singleCert(t *testing.T) { 1062 connState, err := testConnState( 1063 "test-fixtures/root/rootcawextcert.pem", 1064 "test-fixtures/root/rootcawextkey.pem", 1065 "test-fixtures/root/rootcacert.pem", 1066 ) 1067 if err != nil { 1068 t.Fatalf("error testing connection state: %v", err) 1069 } 1070 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 1071 if err != nil { 1072 t.Fatalf("err: %v", err) 1073 } 1074 logicaltest.Test(t, logicaltest.TestCase{ 1075 CredentialBackend: testFactory(t), 1076 Steps: []logicaltest.TestStep{ 1077 testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:A UTF8String Extension"}, false), 1078 testAccStepLogin(t, connState), 1079 testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:*,2.1.1.2:A UTF8*"}, false), 1080 testAccStepLogin(t, connState), 1081 testAccStepCert(t, "web", ca, "foo", allowed{ext: "1.2.3.45:*"}, false), 1082 testAccStepLoginInvalid(t, connState), 1083 testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:The Wrong Value"}, false), 1084 testAccStepLoginInvalid(t, connState), 1085 testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:*,2.1.1.2:The Wrong Value"}, false), 1086 testAccStepLoginInvalid(t, connState), 1087 testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:"}, false), 1088 testAccStepLoginInvalid(t, connState), 1089 testAccStepCert(t, "web", ca, "foo", allowed{ext: "2.1.1.1:,2.1.1.2:*"}, false), 1090 testAccStepLoginInvalid(t, connState), 1091 testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "2.1.1.1:A UTF8String Extension"}, false), 1092 testAccStepLogin(t, connState), 1093 testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "2.1.1.1:*,2.1.1.2:A UTF8*"}, false), 1094 testAccStepLogin(t, connState), 1095 testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "1.2.3.45:*"}, false), 1096 testAccStepLoginInvalid(t, connState), 1097 testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "2.1.1.1:The Wrong Value"}, false), 1098 testAccStepLoginInvalid(t, connState), 1099 testAccStepCert(t, "web", ca, "foo", allowed{names: "example.com", ext: "2.1.1.1:*,2.1.1.2:The Wrong Value"}, false), 1100 testAccStepLoginInvalid(t, connState), 1101 testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "2.1.1.1:A UTF8String Extension"}, false), 1102 testAccStepLoginInvalid(t, connState), 1103 testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "2.1.1.1:*,2.1.1.2:A UTF8*"}, false), 1104 testAccStepLoginInvalid(t, connState), 1105 testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "1.2.3.45:*"}, false), 1106 testAccStepLoginInvalid(t, connState), 1107 testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "2.1.1.1:The Wrong Value"}, false), 1108 testAccStepLoginInvalid(t, connState), 1109 testAccStepCert(t, "web", ca, "foo", allowed{names: "invalid", ext: "2.1.1.1:*,2.1.1.2:The Wrong Value"}, false), 1110 testAccStepLoginInvalid(t, connState), 1111 }, 1112 }) 1113} 1114 1115// Test a self-signed client with URI alt names (root CA) that is trusted 1116func TestBackend_dns_singleCert(t *testing.T) { 1117 certTemplate := &x509.Certificate{ 1118 Subject: pkix.Name{ 1119 CommonName: "example.com", 1120 }, 1121 DNSNames: []string{"example.com"}, 1122 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 1123 ExtKeyUsage: []x509.ExtKeyUsage{ 1124 x509.ExtKeyUsageServerAuth, 1125 x509.ExtKeyUsageClientAuth, 1126 }, 1127 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement, 1128 SerialNumber: big.NewInt(mathrand.Int63()), 1129 NotBefore: time.Now().Add(-30 * time.Second), 1130 NotAfter: time.Now().Add(262980 * time.Hour), 1131 } 1132 1133 tempDir, connState, err := generateTestCertAndConnState(t, certTemplate) 1134 if tempDir != "" { 1135 defer os.RemoveAll(tempDir) 1136 } 1137 if err != nil { 1138 t.Fatalf("error testing connection state: %v", err) 1139 } 1140 ca, err := ioutil.ReadFile(filepath.Join(tempDir, "ca_cert.pem")) 1141 if err != nil { 1142 t.Fatalf("err: %v", err) 1143 } 1144 1145 logicaltest.Test(t, logicaltest.TestCase{ 1146 CredentialBackend: testFactory(t), 1147 Steps: []logicaltest.TestStep{ 1148 testAccStepCert(t, "web", ca, "foo", allowed{dns: "example.com"}, false), 1149 testAccStepLogin(t, connState), 1150 testAccStepCert(t, "web", ca, "foo", allowed{dns: "*ample.com"}, false), 1151 testAccStepLogin(t, connState), 1152 testAccStepCert(t, "web", ca, "foo", allowed{dns: "notincert.com"}, false), 1153 testAccStepLoginInvalid(t, connState), 1154 testAccStepCert(t, "web", ca, "foo", allowed{dns: "abc"}, false), 1155 testAccStepLoginInvalid(t, connState), 1156 testAccStepCert(t, "web", ca, "foo", allowed{dns: "*.example.com"}, false), 1157 testAccStepLoginInvalid(t, connState), 1158 }, 1159 }) 1160} 1161 1162// Test a self-signed client with URI alt names (root CA) that is trusted 1163func TestBackend_email_singleCert(t *testing.T) { 1164 certTemplate := &x509.Certificate{ 1165 Subject: pkix.Name{ 1166 CommonName: "example.com", 1167 }, 1168 EmailAddresses: []string{"valid@example.com"}, 1169 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 1170 ExtKeyUsage: []x509.ExtKeyUsage{ 1171 x509.ExtKeyUsageServerAuth, 1172 x509.ExtKeyUsageClientAuth, 1173 }, 1174 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement, 1175 SerialNumber: big.NewInt(mathrand.Int63()), 1176 NotBefore: time.Now().Add(-30 * time.Second), 1177 NotAfter: time.Now().Add(262980 * time.Hour), 1178 } 1179 1180 tempDir, connState, err := generateTestCertAndConnState(t, certTemplate) 1181 if tempDir != "" { 1182 defer os.RemoveAll(tempDir) 1183 } 1184 if err != nil { 1185 t.Fatalf("error testing connection state: %v", err) 1186 } 1187 ca, err := ioutil.ReadFile(filepath.Join(tempDir, "ca_cert.pem")) 1188 if err != nil { 1189 t.Fatalf("err: %v", err) 1190 } 1191 1192 logicaltest.Test(t, logicaltest.TestCase{ 1193 CredentialBackend: testFactory(t), 1194 Steps: []logicaltest.TestStep{ 1195 testAccStepCert(t, "web", ca, "foo", allowed{emails: "valid@example.com"}, false), 1196 testAccStepLogin(t, connState), 1197 testAccStepCert(t, "web", ca, "foo", allowed{emails: "*@example.com"}, false), 1198 testAccStepLogin(t, connState), 1199 testAccStepCert(t, "web", ca, "foo", allowed{emails: "invalid@notincert.com"}, false), 1200 testAccStepLoginInvalid(t, connState), 1201 testAccStepCert(t, "web", ca, "foo", allowed{emails: "abc"}, false), 1202 testAccStepLoginInvalid(t, connState), 1203 testAccStepCert(t, "web", ca, "foo", allowed{emails: "*.example.com"}, false), 1204 testAccStepLoginInvalid(t, connState), 1205 }, 1206 }) 1207} 1208 1209// Test a self-signed client with OU (root CA) that is trusted 1210func TestBackend_organizationalUnit_singleCert(t *testing.T) { 1211 connState, err := testConnState( 1212 "test-fixtures/root/rootcawoucert.pem", 1213 "test-fixtures/root/rootcawoukey.pem", 1214 "test-fixtures/root/rootcawoucert.pem", 1215 ) 1216 if err != nil { 1217 t.Fatalf("error testing connection state: %v", err) 1218 } 1219 ca, err := ioutil.ReadFile("test-fixtures/root/rootcawoucert.pem") 1220 if err != nil { 1221 t.Fatalf("err: %v", err) 1222 } 1223 logicaltest.Test(t, logicaltest.TestCase{ 1224 CredentialBackend: testFactory(t), 1225 Steps: []logicaltest.TestStep{ 1226 testAccStepCert(t, "web", ca, "foo", allowed{organizational_units: "engineering"}, false), 1227 testAccStepLogin(t, connState), 1228 testAccStepCert(t, "web", ca, "foo", allowed{organizational_units: "eng*"}, false), 1229 testAccStepLogin(t, connState), 1230 testAccStepCert(t, "web", ca, "foo", allowed{organizational_units: "engineering,finance"}, false), 1231 testAccStepLogin(t, connState), 1232 testAccStepCert(t, "web", ca, "foo", allowed{organizational_units: "foo"}, false), 1233 testAccStepLoginInvalid(t, connState), 1234 }, 1235 }) 1236} 1237 1238// Test a self-signed client with URI alt names (root CA) that is trusted 1239func TestBackend_uri_singleCert(t *testing.T) { 1240 u, err := url.Parse("spiffe://example.com/host") 1241 if err != nil { 1242 t.Fatal(err) 1243 } 1244 certTemplate := &x509.Certificate{ 1245 Subject: pkix.Name{ 1246 CommonName: "example.com", 1247 }, 1248 DNSNames: []string{"example.com"}, 1249 IPAddresses: []net.IP{net.ParseIP("127.0.0.1")}, 1250 URIs: []*url.URL{u}, 1251 ExtKeyUsage: []x509.ExtKeyUsage{ 1252 x509.ExtKeyUsageServerAuth, 1253 x509.ExtKeyUsageClientAuth, 1254 }, 1255 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement, 1256 SerialNumber: big.NewInt(mathrand.Int63()), 1257 NotBefore: time.Now().Add(-30 * time.Second), 1258 NotAfter: time.Now().Add(262980 * time.Hour), 1259 } 1260 1261 tempDir, connState, err := generateTestCertAndConnState(t, certTemplate) 1262 if tempDir != "" { 1263 defer os.RemoveAll(tempDir) 1264 } 1265 if err != nil { 1266 t.Fatalf("error testing connection state: %v", err) 1267 } 1268 ca, err := ioutil.ReadFile(filepath.Join(tempDir, "ca_cert.pem")) 1269 if err != nil { 1270 t.Fatalf("err: %v", err) 1271 } 1272 logicaltest.Test(t, logicaltest.TestCase{ 1273 CredentialBackend: testFactory(t), 1274 Steps: []logicaltest.TestStep{ 1275 testAccStepCert(t, "web", ca, "foo", allowed{uris: "spiffe://example.com/*"}, false), 1276 testAccStepLogin(t, connState), 1277 testAccStepCert(t, "web", ca, "foo", allowed{uris: "spiffe://example.com/host"}, false), 1278 testAccStepLogin(t, connState), 1279 testAccStepCert(t, "web", ca, "foo", allowed{uris: "spiffe://example.com/invalid"}, false), 1280 testAccStepLoginInvalid(t, connState), 1281 testAccStepCert(t, "web", ca, "foo", allowed{uris: "abc"}, false), 1282 testAccStepLoginInvalid(t, connState), 1283 testAccStepCert(t, "web", ca, "foo", allowed{uris: "http://www.google.com"}, false), 1284 testAccStepLoginInvalid(t, connState), 1285 }, 1286 }) 1287} 1288 1289// Test against a collection of matching and non-matching rules 1290func TestBackend_mixed_constraints(t *testing.T) { 1291 connState, err := testConnState("test-fixtures/keys/cert.pem", 1292 "test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem") 1293 if err != nil { 1294 t.Fatalf("error testing connection state: %v", err) 1295 } 1296 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 1297 if err != nil { 1298 t.Fatalf("err: %v", err) 1299 } 1300 logicaltest.Test(t, logicaltest.TestCase{ 1301 CredentialBackend: testFactory(t), 1302 Steps: []logicaltest.TestStep{ 1303 testAccStepCert(t, "1unconstrained", ca, "foo", allowed{}, false), 1304 testAccStepCert(t, "2matching", ca, "foo", allowed{names: "*.example.com,whatever"}, false), 1305 testAccStepCert(t, "3invalid", ca, "foo", allowed{names: "invalid"}, false), 1306 testAccStepLogin(t, connState), 1307 // Assumes CertEntries are processed in alphabetical order (due to store.List), so we only match 2matching if 1unconstrained doesn't match 1308 testAccStepLoginWithName(t, connState, "2matching"), 1309 testAccStepLoginWithNameInvalid(t, connState, "3invalid"), 1310 }, 1311 }) 1312} 1313 1314// Test an untrusted client 1315func TestBackend_untrusted(t *testing.T) { 1316 connState, err := testConnState("test-fixtures/keys/cert.pem", 1317 "test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem") 1318 if err != nil { 1319 t.Fatalf("error testing connection state: %v", err) 1320 } 1321 logicaltest.Test(t, logicaltest.TestCase{ 1322 CredentialBackend: testFactory(t), 1323 Steps: []logicaltest.TestStep{ 1324 testAccStepLoginInvalid(t, connState), 1325 }, 1326 }) 1327} 1328 1329func TestBackend_validCIDR(t *testing.T) { 1330 config := logical.TestBackendConfig() 1331 storage := &logical.InmemStorage{} 1332 config.StorageView = storage 1333 1334 b, err := Factory(context.Background(), config) 1335 if err != nil { 1336 t.Fatal(err) 1337 } 1338 1339 connState, err := testConnState("test-fixtures/keys/cert.pem", 1340 "test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem") 1341 if err != nil { 1342 t.Fatalf("error testing connection state: %v", err) 1343 } 1344 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 1345 if err != nil { 1346 t.Fatalf("err: %v", err) 1347 } 1348 1349 name := "web" 1350 boundCIDRs := []string{"127.0.0.1", "128.252.0.0/16"} 1351 1352 addCertReq := &logical.Request{ 1353 Operation: logical.UpdateOperation, 1354 Path: "certs/" + name, 1355 Data: map[string]interface{}{ 1356 "certificate": string(ca), 1357 "policies": "foo", 1358 "display_name": name, 1359 "allowed_names": "", 1360 "required_extensions": "", 1361 "lease": 1000, 1362 "bound_cidrs": boundCIDRs, 1363 }, 1364 Storage: storage, 1365 Connection: &logical.Connection{ConnState: &connState}, 1366 } 1367 1368 _, err = b.HandleRequest(context.Background(), addCertReq) 1369 if err != nil { 1370 t.Fatal(err) 1371 } 1372 1373 readCertReq := &logical.Request{ 1374 Operation: logical.ReadOperation, 1375 Path: "certs/" + name, 1376 Storage: storage, 1377 Connection: &logical.Connection{ConnState: &connState}, 1378 } 1379 1380 readResult, err := b.HandleRequest(context.Background(), readCertReq) 1381 cidrsResult := readResult.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler) 1382 1383 if cidrsResult[0].String() != boundCIDRs[0] || 1384 cidrsResult[1].String() != boundCIDRs[1] { 1385 t.Fatalf("bound_cidrs couldn't be set correctly, EXPECTED: %v, ACTUAL: %v", boundCIDRs, cidrsResult) 1386 } 1387 1388 loginReq := &logical.Request{ 1389 Operation: logical.UpdateOperation, 1390 Path: "login", 1391 Unauthenticated: true, 1392 Data: map[string]interface{}{ 1393 "name": name, 1394 }, 1395 Storage: storage, 1396 Connection: &logical.Connection{ConnState: &connState}, 1397 } 1398 1399 // override the remote address with an IPV4 that is authorized 1400 loginReq.Connection.RemoteAddr = "127.0.0.1/32" 1401 1402 _, err = b.HandleRequest(context.Background(), loginReq) 1403 if err != nil { 1404 t.Fatal(err.Error()) 1405 } 1406} 1407 1408func TestBackend_invalidCIDR(t *testing.T) { 1409 config := logical.TestBackendConfig() 1410 storage := &logical.InmemStorage{} 1411 config.StorageView = storage 1412 1413 b, err := Factory(context.Background(), config) 1414 if err != nil { 1415 t.Fatal(err) 1416 } 1417 1418 connState, err := testConnState("test-fixtures/keys/cert.pem", 1419 "test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem") 1420 if err != nil { 1421 t.Fatalf("error testing connection state: %v", err) 1422 } 1423 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 1424 if err != nil { 1425 t.Fatalf("err: %v", err) 1426 } 1427 1428 name := "web" 1429 1430 addCertReq := &logical.Request{ 1431 Operation: logical.UpdateOperation, 1432 Path: "certs/" + name, 1433 Data: map[string]interface{}{ 1434 "certificate": string(ca), 1435 "policies": "foo", 1436 "display_name": name, 1437 "allowed_names": "", 1438 "required_extensions": "", 1439 "lease": 1000, 1440 "bound_cidrs": []string{"127.0.0.1/32", "128.252.0.0/16"}, 1441 }, 1442 Storage: storage, 1443 Connection: &logical.Connection{ConnState: &connState}, 1444 } 1445 1446 _, err = b.HandleRequest(context.Background(), addCertReq) 1447 if err != nil { 1448 t.Fatal(err) 1449 } 1450 1451 loginReq := &logical.Request{ 1452 Operation: logical.UpdateOperation, 1453 Path: "login", 1454 Unauthenticated: true, 1455 Data: map[string]interface{}{ 1456 "name": name, 1457 }, 1458 Storage: storage, 1459 Connection: &logical.Connection{ConnState: &connState}, 1460 } 1461 1462 // override the remote address with an IPV4 that isn't authorized 1463 loginReq.Connection.RemoteAddr = "127.0.0.1/8" 1464 1465 _, err = b.HandleRequest(context.Background(), loginReq) 1466 if err == nil { 1467 t.Fatal("expected \"ERROR: permission denied\"") 1468 } 1469} 1470 1471func testAccStepAddCRL(t *testing.T, crl []byte, connState tls.ConnectionState) logicaltest.TestStep { 1472 return logicaltest.TestStep{ 1473 Operation: logical.UpdateOperation, 1474 Path: "crls/test", 1475 ConnState: &connState, 1476 Data: map[string]interface{}{ 1477 "crl": crl, 1478 }, 1479 } 1480} 1481 1482func testAccStepReadCRL(t *testing.T, connState tls.ConnectionState) logicaltest.TestStep { 1483 return logicaltest.TestStep{ 1484 Operation: logical.ReadOperation, 1485 Path: "crls/test", 1486 ConnState: &connState, 1487 Check: func(resp *logical.Response) error { 1488 crlInfo := CRLInfo{} 1489 err := mapstructure.Decode(resp.Data, &crlInfo) 1490 if err != nil { 1491 t.Fatalf("err: %v", err) 1492 } 1493 if len(crlInfo.Serials) != 1 { 1494 t.Fatalf("bad: expected CRL with length 1, got %d", len(crlInfo.Serials)) 1495 } 1496 if _, ok := crlInfo.Serials["637101449987587619778072672905061040630001617053"]; !ok { 1497 t.Fatalf("bad: expected serial number not found in CRL") 1498 } 1499 return nil 1500 }, 1501 } 1502} 1503 1504func testAccStepDeleteCRL(t *testing.T, connState tls.ConnectionState) logicaltest.TestStep { 1505 return logicaltest.TestStep{ 1506 Operation: logical.DeleteOperation, 1507 Path: "crls/test", 1508 ConnState: &connState, 1509 } 1510} 1511 1512func testAccStepLogin(t *testing.T, connState tls.ConnectionState) logicaltest.TestStep { 1513 return testAccStepLoginWithName(t, connState, "") 1514} 1515 1516func testAccStepLoginWithName(t *testing.T, connState tls.ConnectionState, certName string) logicaltest.TestStep { 1517 return logicaltest.TestStep{ 1518 Operation: logical.UpdateOperation, 1519 Path: "login", 1520 Unauthenticated: true, 1521 ConnState: &connState, 1522 Check: func(resp *logical.Response) error { 1523 if resp.Auth.TTL != 1000*time.Second { 1524 t.Fatalf("bad lease length: %#v", resp.Auth) 1525 } 1526 1527 if certName != "" && resp.Auth.DisplayName != ("mnt-"+certName) { 1528 t.Fatalf("matched the wrong cert: %#v", resp.Auth.DisplayName) 1529 } 1530 1531 fn := logicaltest.TestCheckAuth([]string{"default", "foo"}) 1532 return fn(resp) 1533 }, 1534 Data: map[string]interface{}{ 1535 "name": certName, 1536 }, 1537 } 1538} 1539 1540func testAccStepLoginDefaultLease(t *testing.T, connState tls.ConnectionState) logicaltest.TestStep { 1541 return logicaltest.TestStep{ 1542 Operation: logical.UpdateOperation, 1543 Path: "login", 1544 Unauthenticated: true, 1545 ConnState: &connState, 1546 Check: func(resp *logical.Response) error { 1547 if resp.Auth.TTL != 1000*time.Second { 1548 t.Fatalf("bad lease length: %#v", resp.Auth) 1549 } 1550 1551 fn := logicaltest.TestCheckAuth([]string{"default", "foo"}) 1552 return fn(resp) 1553 }, 1554 } 1555} 1556 1557func testAccStepLoginInvalid(t *testing.T, connState tls.ConnectionState) logicaltest.TestStep { 1558 return testAccStepLoginWithNameInvalid(t, connState, "") 1559} 1560 1561func testAccStepLoginWithNameInvalid(t *testing.T, connState tls.ConnectionState, certName string) logicaltest.TestStep { 1562 return logicaltest.TestStep{ 1563 Operation: logical.UpdateOperation, 1564 Path: "login", 1565 Unauthenticated: true, 1566 ConnState: &connState, 1567 Check: func(resp *logical.Response) error { 1568 if resp.Auth != nil { 1569 return fmt.Errorf("should not be authorized: %#v", resp) 1570 } 1571 return nil 1572 }, 1573 Data: map[string]interface{}{ 1574 "name": certName, 1575 }, 1576 ErrorOk: true, 1577 } 1578} 1579 1580func testAccStepListCerts( 1581 t *testing.T, certs []string) []logicaltest.TestStep { 1582 return []logicaltest.TestStep{ 1583 logicaltest.TestStep{ 1584 Operation: logical.ListOperation, 1585 Path: "certs", 1586 Check: func(resp *logical.Response) error { 1587 if resp == nil { 1588 return fmt.Errorf("nil response") 1589 } 1590 if resp.Data == nil { 1591 return fmt.Errorf("nil data") 1592 } 1593 if resp.Data["keys"] == interface{}(nil) { 1594 return fmt.Errorf("nil keys") 1595 } 1596 keys := resp.Data["keys"].([]string) 1597 if !reflect.DeepEqual(keys, certs) { 1598 return fmt.Errorf("mismatch: keys is %#v, certs is %#v", keys, certs) 1599 } 1600 return nil 1601 }, 1602 }, logicaltest.TestStep{ 1603 Operation: logical.ListOperation, 1604 Path: "certs/", 1605 Check: func(resp *logical.Response) error { 1606 if resp == nil { 1607 return fmt.Errorf("nil response") 1608 } 1609 if resp.Data == nil { 1610 return fmt.Errorf("nil data") 1611 } 1612 if resp.Data["keys"] == interface{}(nil) { 1613 return fmt.Errorf("nil keys") 1614 } 1615 keys := resp.Data["keys"].([]string) 1616 if !reflect.DeepEqual(keys, certs) { 1617 return fmt.Errorf("mismatch: keys is %#v, certs is %#v", keys, certs) 1618 } 1619 1620 return nil 1621 }, 1622 }, 1623 } 1624} 1625 1626type allowed struct { 1627 names string // allowed names in the certificate, looks at common, name, dns, email [depricated] 1628 common_names string // allowed common names in the certificate 1629 dns string // allowed dns names in the SAN extension of the certificate 1630 emails string // allowed email names in SAN extension of the certificate 1631 uris string // allowed uris in SAN extension of the certificate 1632 organizational_units string // allowed OUs in the certificate 1633 ext string // required extensions in the certificate 1634} 1635 1636func testAccStepCert( 1637 t *testing.T, name string, cert []byte, policies string, testData allowed, expectError bool) logicaltest.TestStep { 1638 return logicaltest.TestStep{ 1639 Operation: logical.UpdateOperation, 1640 Path: "certs/" + name, 1641 ErrorOk: expectError, 1642 Data: map[string]interface{}{ 1643 "certificate": string(cert), 1644 "policies": policies, 1645 "display_name": name, 1646 "allowed_names": testData.names, 1647 "allowed_common_names": testData.common_names, 1648 "allowed_dns_sans": testData.dns, 1649 "allowed_email_sans": testData.emails, 1650 "allowed_uri_sans": testData.uris, 1651 "allowed_organizational_units": testData.organizational_units, 1652 "required_extensions": testData.ext, 1653 "lease": 1000, 1654 }, 1655 Check: func(resp *logical.Response) error { 1656 if resp == nil && expectError { 1657 return fmt.Errorf("expected error but received nil") 1658 } 1659 return nil 1660 }, 1661 } 1662} 1663 1664func testAccStepCertLease( 1665 t *testing.T, name string, cert []byte, policies string) logicaltest.TestStep { 1666 return logicaltest.TestStep{ 1667 Operation: logical.UpdateOperation, 1668 Path: "certs/" + name, 1669 Data: map[string]interface{}{ 1670 "certificate": string(cert), 1671 "policies": policies, 1672 "display_name": name, 1673 "lease": 1000, 1674 }, 1675 } 1676} 1677 1678func testAccStepCertTTL( 1679 t *testing.T, name string, cert []byte, policies string) logicaltest.TestStep { 1680 return logicaltest.TestStep{ 1681 Operation: logical.UpdateOperation, 1682 Path: "certs/" + name, 1683 Data: map[string]interface{}{ 1684 "certificate": string(cert), 1685 "policies": policies, 1686 "display_name": name, 1687 "ttl": "1000s", 1688 }, 1689 } 1690} 1691 1692func testAccStepCertMaxTTL( 1693 t *testing.T, name string, cert []byte, policies string) logicaltest.TestStep { 1694 return logicaltest.TestStep{ 1695 Operation: logical.UpdateOperation, 1696 Path: "certs/" + name, 1697 Data: map[string]interface{}{ 1698 "certificate": string(cert), 1699 "policies": policies, 1700 "display_name": name, 1701 "ttl": "1000s", 1702 "max_ttl": "1200s", 1703 }, 1704 } 1705} 1706 1707func testAccStepCertNoLease( 1708 t *testing.T, name string, cert []byte, policies string) logicaltest.TestStep { 1709 return logicaltest.TestStep{ 1710 Operation: logical.UpdateOperation, 1711 Path: "certs/" + name, 1712 Data: map[string]interface{}{ 1713 "certificate": string(cert), 1714 "policies": policies, 1715 "display_name": name, 1716 }, 1717 } 1718} 1719 1720func testConnState(certPath, keyPath, rootCertPath string) (tls.ConnectionState, error) { 1721 cert, err := tls.LoadX509KeyPair(certPath, keyPath) 1722 if err != nil { 1723 return tls.ConnectionState{}, err 1724 } 1725 rootConfig := &rootcerts.Config{ 1726 CAFile: rootCertPath, 1727 } 1728 rootCAs, err := rootcerts.LoadCACerts(rootConfig) 1729 if err != nil { 1730 return tls.ConnectionState{}, err 1731 } 1732 listenConf := &tls.Config{ 1733 Certificates: []tls.Certificate{cert}, 1734 ClientAuth: tls.RequestClientCert, 1735 InsecureSkipVerify: false, 1736 RootCAs: rootCAs, 1737 } 1738 dialConf := listenConf.Clone() 1739 // start a server 1740 list, err := tls.Listen("tcp", "127.0.0.1:0", listenConf) 1741 if err != nil { 1742 return tls.ConnectionState{}, err 1743 } 1744 defer list.Close() 1745 1746 // Accept connections. 1747 serverErrors := make(chan error, 1) 1748 connState := make(chan tls.ConnectionState) 1749 go func() { 1750 defer close(connState) 1751 serverConn, err := list.Accept() 1752 serverErrors <- err 1753 if err != nil { 1754 close(serverErrors) 1755 return 1756 } 1757 defer serverConn.Close() 1758 1759 // Read the ping 1760 buf := make([]byte, 4) 1761 _, err = serverConn.Read(buf) 1762 if (err != nil) && (err != io.EOF) { 1763 serverErrors <- err 1764 close(serverErrors) 1765 return 1766 } else { 1767 // EOF is a reasonable error condition, so swallow it. 1768 serverErrors <- nil 1769 } 1770 close(serverErrors) 1771 connState <- serverConn.(*tls.Conn).ConnectionState() 1772 }() 1773 1774 // Establish a connection from the client side and write a few bytes. 1775 clientErrors := make(chan error, 1) 1776 go func() { 1777 addr := list.Addr().String() 1778 conn, err := tls.Dial("tcp", addr, dialConf) 1779 clientErrors <- err 1780 if err != nil { 1781 close(clientErrors) 1782 return 1783 } 1784 defer conn.Close() 1785 1786 // Write ping 1787 _, err = conn.Write([]byte("ping")) 1788 clientErrors <- err 1789 close(clientErrors) 1790 }() 1791 1792 for err = range clientErrors { 1793 if err != nil { 1794 return tls.ConnectionState{}, fmt.Errorf("error in client goroutine:%v", err) 1795 } 1796 } 1797 1798 for err = range serverErrors { 1799 if err != nil { 1800 return tls.ConnectionState{}, fmt.Errorf("error in server goroutine:%v", err) 1801 } 1802 } 1803 // Grab the current state 1804 return <-connState, nil 1805} 1806 1807func Test_Renew(t *testing.T) { 1808 storage := &logical.InmemStorage{} 1809 1810 lb, err := Factory(context.Background(), &logical.BackendConfig{ 1811 System: &logical.StaticSystemView{ 1812 DefaultLeaseTTLVal: 300 * time.Second, 1813 MaxLeaseTTLVal: 1800 * time.Second, 1814 }, 1815 StorageView: storage, 1816 }) 1817 if err != nil { 1818 t.Fatalf("error: %s", err) 1819 } 1820 1821 b := lb.(*backend) 1822 connState, err := testConnState("test-fixtures/keys/cert.pem", 1823 "test-fixtures/keys/key.pem", "test-fixtures/root/rootcacert.pem") 1824 if err != nil { 1825 t.Fatalf("error testing connection state: %v", err) 1826 } 1827 ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem") 1828 if err != nil { 1829 t.Fatal(err) 1830 } 1831 1832 req := &logical.Request{ 1833 Connection: &logical.Connection{ 1834 ConnState: &connState, 1835 }, 1836 Storage: storage, 1837 Auth: &logical.Auth{}, 1838 } 1839 1840 fd := &framework.FieldData{ 1841 Raw: map[string]interface{}{ 1842 "name": "test", 1843 "certificate": ca, 1844 "policies": "foo,bar", 1845 }, 1846 Schema: pathCerts(b).Fields, 1847 } 1848 1849 resp, err := b.pathCertWrite(context.Background(), req, fd) 1850 if err != nil { 1851 t.Fatal(err) 1852 } 1853 1854 empty_login_fd := &framework.FieldData{ 1855 Raw: map[string]interface{}{}, 1856 Schema: pathLogin(b).Fields, 1857 } 1858 resp, err = b.pathLogin(context.Background(), req, empty_login_fd) 1859 if err != nil { 1860 t.Fatal(err) 1861 } 1862 if resp.IsError() { 1863 t.Fatalf("got error: %#v", *resp) 1864 } 1865 req.Auth.InternalData = resp.Auth.InternalData 1866 req.Auth.Metadata = resp.Auth.Metadata 1867 req.Auth.LeaseOptions = resp.Auth.LeaseOptions 1868 req.Auth.Policies = resp.Auth.Policies 1869 req.Auth.TokenPolicies = req.Auth.Policies 1870 req.Auth.Period = resp.Auth.Period 1871 1872 // Normal renewal 1873 resp, err = b.pathLoginRenew(context.Background(), req, empty_login_fd) 1874 if err != nil { 1875 t.Fatal(err) 1876 } 1877 if resp == nil { 1878 t.Fatal("got nil response from renew") 1879 } 1880 if resp.IsError() { 1881 t.Fatalf("got error: %#v", *resp) 1882 } 1883 1884 // Change the policies -- this should fail 1885 fd.Raw["policies"] = "zip,zap" 1886 resp, err = b.pathCertWrite(context.Background(), req, fd) 1887 if err != nil { 1888 t.Fatal(err) 1889 } 1890 1891 resp, err = b.pathLoginRenew(context.Background(), req, empty_login_fd) 1892 if err == nil { 1893 t.Fatal("expected error") 1894 } 1895 1896 // Put the policies back, this should be okay 1897 fd.Raw["policies"] = "bar,foo" 1898 resp, err = b.pathCertWrite(context.Background(), req, fd) 1899 if err != nil { 1900 t.Fatal(err) 1901 } 1902 1903 resp, err = b.pathLoginRenew(context.Background(), req, empty_login_fd) 1904 if err != nil { 1905 t.Fatal(err) 1906 } 1907 if resp == nil { 1908 t.Fatal("got nil response from renew") 1909 } 1910 if resp.IsError() { 1911 t.Fatalf("got error: %#v", *resp) 1912 } 1913 1914 // Add period value to cert entry 1915 period := 350 * time.Second 1916 fd.Raw["period"] = period.String() 1917 resp, err = b.pathCertWrite(context.Background(), req, fd) 1918 if err != nil { 1919 t.Fatal(err) 1920 } 1921 1922 resp, err = b.pathLoginRenew(context.Background(), req, empty_login_fd) 1923 if err != nil { 1924 t.Fatal(err) 1925 } 1926 if resp == nil { 1927 t.Fatal("got nil response from renew") 1928 } 1929 if resp.IsError() { 1930 t.Fatalf("got error: %#v", *resp) 1931 } 1932 1933 if resp.Auth.Period != period { 1934 t.Fatalf("expected a period value of %s in the response, got: %s", period, resp.Auth.Period) 1935 } 1936 1937 // Delete CA, make sure we can't renew 1938 resp, err = b.pathCertDelete(context.Background(), req, fd) 1939 if err != nil { 1940 t.Fatal(err) 1941 } 1942 1943 resp, err = b.pathLoginRenew(context.Background(), req, empty_login_fd) 1944 if err != nil { 1945 t.Fatal(err) 1946 } 1947 if resp == nil { 1948 t.Fatal("got nil response from renew") 1949 } 1950 if !resp.IsError() { 1951 t.Fatal("expected error") 1952 } 1953} 1954 1955func TestBackend_CertUpgrade(t *testing.T) { 1956 s := &logical.InmemStorage{} 1957 1958 config := logical.TestBackendConfig() 1959 config.StorageView = s 1960 1961 ctx := context.Background() 1962 1963 b := Backend() 1964 if b == nil { 1965 t.Fatalf("failed to create backend") 1966 } 1967 if err := b.Setup(ctx, config); err != nil { 1968 t.Fatal(err) 1969 } 1970 1971 foo := &CertEntry{ 1972 Policies: []string{"foo"}, 1973 Period: time.Second, 1974 TTL: time.Second, 1975 MaxTTL: time.Second, 1976 BoundCIDRs: []*sockaddr.SockAddrMarshaler{&sockaddr.SockAddrMarshaler{SockAddr: sockaddr.MustIPAddr("127.0.0.1")}}, 1977 } 1978 1979 entry, err := logical.StorageEntryJSON("cert/foo", foo) 1980 if err != nil { 1981 t.Fatal(err) 1982 } 1983 err = s.Put(ctx, entry) 1984 if err != nil { 1985 t.Fatal(err) 1986 } 1987 1988 certEntry, err := b.Cert(ctx, s, "foo") 1989 if err != nil { 1990 t.Fatal(err) 1991 } 1992 1993 exp := &CertEntry{ 1994 Policies: []string{"foo"}, 1995 Period: time.Second, 1996 TTL: time.Second, 1997 MaxTTL: time.Second, 1998 BoundCIDRs: []*sockaddr.SockAddrMarshaler{&sockaddr.SockAddrMarshaler{SockAddr: sockaddr.MustIPAddr("127.0.0.1")}}, 1999 TokenParams: tokenutil.TokenParams{ 2000 TokenPolicies: []string{"foo"}, 2001 TokenPeriod: time.Second, 2002 TokenTTL: time.Second, 2003 TokenMaxTTL: time.Second, 2004 TokenBoundCIDRs: []*sockaddr.SockAddrMarshaler{&sockaddr.SockAddrMarshaler{SockAddr: sockaddr.MustIPAddr("127.0.0.1")}}, 2005 }, 2006 } 2007 if diff := deep.Equal(certEntry, exp); diff != nil { 2008 t.Fatal(diff) 2009 } 2010} 2011