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