consul/agent/connect_ca_endpoint_test.go

305 lines
7.1 KiB
Go
Raw Normal View History

// Copyright (c) HashiCorp, Inc.
[COMPLIANCE] License changes (#18443) * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2023-08-11 13:12:13 +00:00
// SPDX-License-Identifier: BUSL-1.1
2018-03-20 17:36:05 +00:00
package agent
import (
2018-05-04 22:28:11 +00:00
"bytes"
"crypto/x509"
2022-04-14 20:55:10 +00:00
"encoding/pem"
"io"
2018-03-20 17:36:05 +00:00
"net/http"
"net/http/httptest"
"testing"
"github.com/hashicorp/consul/testrpc"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/assert"
2018-03-21 17:20:35 +00:00
"github.com/hashicorp/consul/agent/connect"
2018-03-20 17:36:05 +00:00
"github.com/hashicorp/consul/agent/structs"
)
func TestConnectCARoots_empty(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}
2018-03-20 17:36:05 +00:00
t.Parallel()
a := NewTestAgent(t, "connect { enabled = false }")
2018-03-20 17:36:05 +00:00
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
2018-03-20 17:36:05 +00:00
req, _ := http.NewRequest("GET", "/v1/connect/ca/roots", nil)
resp := httptest.NewRecorder()
_, err := a.srv.ConnectCARoots(resp, req)
Format certificates properly (rfc7468) with a trailing new line (#10411) * trim carriage return from certificates when inserting rootCA in the inMemDB * format rootCA properly when returning the CA on the connect CA endpoint * Fix linter warnings * Fix providers to trim certs before returning it * trim newlines on write when possible * add changelog * make sure all provider return a trailing newline after the root and intermediate certs * Fix endpoint to return trailing new line * Fix failing test with vault provider * make test more robust * make sure all provider return a trailing newline after the leaf certs * Check for suffix before removing newline and use function * Add comment to consul provider * Update change log Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * fix typo * simplify code callflow Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * extract requireNewLine as shared func * remove dependency to testify in testing file * remove extra newline in vault provider * Add cert newline fix to envoy xds * remove new line from mock provider * Remove adding a new line from provider and fix it when the cert is read * Add a comment to explain the fix * Add missing for leaf certs * fix missing new line * fix missing new line in leaf certs * remove extra new line in test * updage changelog Co-authored-by: Daniel Nephin <dnephin@hashicorp.com> * fix in vault provider and when reading cache (RPC call) * fix AWS provider * fix failing test in the provider * remove comments and empty lines * add check for empty cert in test * fix linter warnings * add new line for leaf and private key * use string concat instead of Sprintf * fix new lines for leaf signing * preallocate slice and remove append * Add new line to `SignIntermediate` and `CrossSignCA` Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> Co-authored-by: Daniel Nephin <dnephin@hashicorp.com>
2021-07-01 00:48:29 +00:00
require.Error(t, err)
require.Contains(t, err.Error(), "Connect must be enabled")
2018-03-20 17:36:05 +00:00
}
func TestConnectCARoots_list(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}
t.Parallel()
a := NewTestAgent(t, "")
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
// Set some CAs. Note that NewTestAgent already bootstraps one CA so this just
// adds a second and makes it active.
ca2 := connect.TestCAConfigSet(t, a, nil)
2018-03-21 17:20:35 +00:00
// List
req, _ := http.NewRequest("GET", "/v1/connect/ca/roots", nil)
resp := httptest.NewRecorder()
obj, err := a.srv.ConnectCARoots(resp, req)
assert.NoError(t, err)
value := obj.(structs.IndexedCARoots)
assert.Equal(t, value.ActiveRootID, ca2.ID)
assert.Len(t, value.Roots, 2)
2018-03-21 17:20:35 +00:00
// We should never have the secret information
for _, r := range value.Roots {
assert.Equal(t, "", r.SigningCert)
assert.Equal(t, "", r.SigningKey)
2018-03-21 17:20:35 +00:00
}
}
2018-05-04 22:28:11 +00:00
func TestConnectCAConfig(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}
2018-05-04 22:28:11 +00:00
t.Parallel()
tests := []struct {
name string
initialState string
body string
wantErr bool
wantCfg structs.CAConfiguration
}{
{
name: "basic",
body: `
{
"Provider": "consul",
"Config": {
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h"
}
}`,
wantErr: false,
wantCfg: structs.CAConfiguration{
Provider: "consul",
ClusterID: connect.TestClusterID,
Config: map[string]interface{}{
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h",
},
},
},
{
name: "basic with IntermediateCertTTL",
body: `
{
"Provider": "consul",
"Config": {
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h"
}
}`,
wantErr: false,
wantCfg: structs.CAConfiguration{
Provider: "consul",
ClusterID: connect.TestClusterID,
Config: map[string]interface{}{
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h",
},
},
},
{
name: "force without cross sign CamelCase",
body: `
{
"Provider": "consul",
"Config": {
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h"
},
"ForceWithoutCrossSigning": true
}`,
wantErr: false,
wantCfg: structs.CAConfiguration{
Provider: "consul",
ClusterID: connect.TestClusterID,
Config: map[string]interface{}{
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h",
},
ForceWithoutCrossSigning: true,
},
},
{
name: "force without cross sign snake_case",
// Note that config is still CamelCase. We don't currently support snake
// case config in the API only in config files for this. Arguably that's a
// bug but it's unrelated to the force options being tested here so we'll
// only test the new behaviour here rather than scope creep to refactoring
// all the CA config handling.
body: `
{
"provider": "consul",
"config": {
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h"
},
"force_without_cross_signing": true
}`,
wantErr: false,
wantCfg: structs.CAConfiguration{
Provider: "consul",
ClusterID: connect.TestClusterID,
Config: map[string]interface{}{
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h",
},
ForceWithoutCrossSigning: true,
},
},
{
name: "setting state fails",
body: `
{
"Provider": "consul",
"State": {
"foo": "bar"
}
}`,
wantErr: true,
},
{
name: "updating config with same state",
initialState: `foo = "bar"`,
body: `
{
"Provider": "consul",
"config": {
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h"
},
"State": {
"foo": "bar"
}
}`,
wantErr: false,
wantCfg: structs.CAConfiguration{
Provider: "consul",
ClusterID: connect.TestClusterID,
Config: map[string]interface{}{
"LeafCertTTL": "72h",
"IntermediateCertTTL": "288h",
},
State: map[string]string{
"foo": "bar",
},
},
},
2018-05-04 22:28:11 +00:00
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
hcl := ""
if tc.initialState != "" {
hcl = `
connect {
enabled = true
ca_provider = "consul"
ca_config {
intermediate_cert_ttl = "288h"
test_state {
` + tc.initialState + `
}
}
}`
}
a := NewTestAgent(t, hcl)
defer a.Shutdown()
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
// Set the config.
{
body := bytes.NewBuffer([]byte(tc.body))
req, _ := http.NewRequest("PUT", "/v1/connect/ca/configuration", body)
resp := httptest.NewRecorder()
_, err := a.srv.ConnectCAConfiguration(resp, req)
if tc.wantErr {
Format certificates properly (rfc7468) with a trailing new line (#10411) * trim carriage return from certificates when inserting rootCA in the inMemDB * format rootCA properly when returning the CA on the connect CA endpoint * Fix linter warnings * Fix providers to trim certs before returning it * trim newlines on write when possible * add changelog * make sure all provider return a trailing newline after the root and intermediate certs * Fix endpoint to return trailing new line * Fix failing test with vault provider * make test more robust * make sure all provider return a trailing newline after the leaf certs * Check for suffix before removing newline and use function * Add comment to consul provider * Update change log Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * fix typo * simplify code callflow Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * extract requireNewLine as shared func * remove dependency to testify in testing file * remove extra newline in vault provider * Add cert newline fix to envoy xds * remove new line from mock provider * Remove adding a new line from provider and fix it when the cert is read * Add a comment to explain the fix * Add missing for leaf certs * fix missing new line * fix missing new line in leaf certs * remove extra new line in test * updage changelog Co-authored-by: Daniel Nephin <dnephin@hashicorp.com> * fix in vault provider and when reading cache (RPC call) * fix AWS provider * fix failing test in the provider * remove comments and empty lines * add check for empty cert in test * fix linter warnings * add new line for leaf and private key * use string concat instead of Sprintf * fix new lines for leaf signing * preallocate slice and remove append * Add new line to `SignIntermediate` and `CrossSignCA` Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> Co-authored-by: Daniel Nephin <dnephin@hashicorp.com>
2021-07-01 00:48:29 +00:00
require.Error(t, err)
return
}
Format certificates properly (rfc7468) with a trailing new line (#10411) * trim carriage return from certificates when inserting rootCA in the inMemDB * format rootCA properly when returning the CA on the connect CA endpoint * Fix linter warnings * Fix providers to trim certs before returning it * trim newlines on write when possible * add changelog * make sure all provider return a trailing newline after the root and intermediate certs * Fix endpoint to return trailing new line * Fix failing test with vault provider * make test more robust * make sure all provider return a trailing newline after the leaf certs * Check for suffix before removing newline and use function * Add comment to consul provider * Update change log Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * fix typo * simplify code callflow Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * extract requireNewLine as shared func * remove dependency to testify in testing file * remove extra newline in vault provider * Add cert newline fix to envoy xds * remove new line from mock provider * Remove adding a new line from provider and fix it when the cert is read * Add a comment to explain the fix * Add missing for leaf certs * fix missing new line * fix missing new line in leaf certs * remove extra new line in test * updage changelog Co-authored-by: Daniel Nephin <dnephin@hashicorp.com> * fix in vault provider and when reading cache (RPC call) * fix AWS provider * fix failing test in the provider * remove comments and empty lines * add check for empty cert in test * fix linter warnings * add new line for leaf and private key * use string concat instead of Sprintf * fix new lines for leaf signing * preallocate slice and remove append * Add new line to `SignIntermediate` and `CrossSignCA` Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> Co-authored-by: Daniel Nephin <dnephin@hashicorp.com>
2021-07-01 00:48:29 +00:00
require.NoError(t, err)
}
// The config should be updated now.
{
req, _ := http.NewRequest("GET", "/v1/connect/ca/configuration", nil)
resp := httptest.NewRecorder()
obj, err := a.srv.ConnectCAConfiguration(resp, req)
Format certificates properly (rfc7468) with a trailing new line (#10411) * trim carriage return from certificates when inserting rootCA in the inMemDB * format rootCA properly when returning the CA on the connect CA endpoint * Fix linter warnings * Fix providers to trim certs before returning it * trim newlines on write when possible * add changelog * make sure all provider return a trailing newline after the root and intermediate certs * Fix endpoint to return trailing new line * Fix failing test with vault provider * make test more robust * make sure all provider return a trailing newline after the leaf certs * Check for suffix before removing newline and use function * Add comment to consul provider * Update change log Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * fix typo * simplify code callflow Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * extract requireNewLine as shared func * remove dependency to testify in testing file * remove extra newline in vault provider * Add cert newline fix to envoy xds * remove new line from mock provider * Remove adding a new line from provider and fix it when the cert is read * Add a comment to explain the fix * Add missing for leaf certs * fix missing new line * fix missing new line in leaf certs * remove extra new line in test * updage changelog Co-authored-by: Daniel Nephin <dnephin@hashicorp.com> * fix in vault provider and when reading cache (RPC call) * fix AWS provider * fix failing test in the provider * remove comments and empty lines * add check for empty cert in test * fix linter warnings * add new line for leaf and private key * use string concat instead of Sprintf * fix new lines for leaf signing * preallocate slice and remove append * Add new line to `SignIntermediate` and `CrossSignCA` Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> Co-authored-by: Daniel Nephin <dnephin@hashicorp.com>
2021-07-01 00:48:29 +00:00
require.NoError(t, err)
got := obj.(structs.CAConfiguration)
// Reset Raft indexes to make it non flaky
got.CreateIndex = 0
got.ModifyIndex = 0
Format certificates properly (rfc7468) with a trailing new line (#10411) * trim carriage return from certificates when inserting rootCA in the inMemDB * format rootCA properly when returning the CA on the connect CA endpoint * Fix linter warnings * Fix providers to trim certs before returning it * trim newlines on write when possible * add changelog * make sure all provider return a trailing newline after the root and intermediate certs * Fix endpoint to return trailing new line * Fix failing test with vault provider * make test more robust * make sure all provider return a trailing newline after the leaf certs * Check for suffix before removing newline and use function * Add comment to consul provider * Update change log Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * fix typo * simplify code callflow Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> * extract requireNewLine as shared func * remove dependency to testify in testing file * remove extra newline in vault provider * Add cert newline fix to envoy xds * remove new line from mock provider * Remove adding a new line from provider and fix it when the cert is read * Add a comment to explain the fix * Add missing for leaf certs * fix missing new line * fix missing new line in leaf certs * remove extra new line in test * updage changelog Co-authored-by: Daniel Nephin <dnephin@hashicorp.com> * fix in vault provider and when reading cache (RPC call) * fix AWS provider * fix failing test in the provider * remove comments and empty lines * add check for empty cert in test * fix linter warnings * add new line for leaf and private key * use string concat instead of Sprintf * fix new lines for leaf signing * preallocate slice and remove append * Add new line to `SignIntermediate` and `CrossSignCA` Co-authored-by: R.B. Boyer <4903+rboyer@users.noreply.github.com> Co-authored-by: Daniel Nephin <dnephin@hashicorp.com>
2021-07-01 00:48:29 +00:00
require.Equal(t, tc.wantCfg, got)
}
})
2018-05-04 22:28:11 +00:00
}
}
func TestConnectCARoots_PEMEncoding(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}
primary := NewTestAgent(t, "")
defer primary.Shutdown()
testrpc.WaitForActiveCARoot(t, primary.RPC, "dc1", nil)
secondary := NewTestAgent(t, `
primary_datacenter = "dc1"
datacenter = "dc2"
retry_join_wan = ["`+primary.Config.SerfBindAddrWAN.String()+`"]
`)
defer secondary.Shutdown()
testrpc.WaitForActiveCARoot(t, secondary.RPC, "dc2", nil)
req, _ := http.NewRequest("GET", "/v1/connect/ca/roots?pem=true", nil)
recorder := httptest.NewRecorder()
obj, err := secondary.srv.ConnectCARoots(recorder, req)
require.NoError(t, err)
require.Nil(t, obj, "Endpoint returned an object for serialization when it should have returned nil and written to the responses")
resp := recorder.Result()
require.Equal(t, resp.Header.Get("Content-Type"), "application/pem-certificate-chain")
data, err := io.ReadAll(resp.Body)
require.NoError(t, err)
2022-04-14 20:55:10 +00:00
// expecting the root cert from dc1 and an intermediate in dc2
2022-04-14 20:55:10 +00:00
block, rest := pem.Decode(data)
_, err = x509.ParseCertificate(block.Bytes)
require.NoError(t, err)
block, _ = pem.Decode(rest)
_, err = x509.ParseCertificate(block.Bytes)
require.NoError(t, err)
}