Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add intermediates_path option to x509pop node attestor #524

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/plugin_agent_nodeattestor_x509pop.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ spiffe://<trust domain>/spire/agent/x509pop/<fingerprint>
| `trust_domain` | The trust domain that the node belongs to. | |
| `private_key_path` | The path to the private key on disk (PEM encoded PKCS1 or PKCS8) | |
| `certificate_path` | The path to the certificate bundle on disk. The file must contain one or more PEM blocks, starting with the identity certificate followed by any intermediate certificates necessary for chain-of-trust validation. | |
| `intermediates_path` | Optional. The path to a chain of intermediate certificates on disk. The file must contain one or more PEM blocks, corresponding to intermediate certificates necessary for chain-of-trust validation. If the file pointed by `certificate_path` contains more than one certificate, this chain of certificates will be appended to it. | |
25 changes: 21 additions & 4 deletions pkg/agent/plugin/nodeattestor/x509pop/x509pop.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
"sync"

"github.com/hashicorp/hcl"
"github.com/spiffe/spire/pkg/common/plugin/x509pop"
"github.com/spiffe/spire/pkg/common/util"
"github.com/spiffe/spire/proto/agent/nodeattestor"
"github.com/spiffe/spire/proto/common"
"github.com/spiffe/spire/proto/common/plugin"
Expand All @@ -28,9 +30,10 @@ type configData struct {
}

type X509PoPConfig struct {
TrustDomain string `hcl:"trust_domain"`
PrivateKeyPath string `hcl:"private_key_path"`
CertificatePath string `hcl:"certificate_path"`
TrustDomain string `hcl:"trust_domain"`
PrivateKeyPath string `hcl:"private_key_path"`
CertificatePath string `hcl:"certificate_path"`
IntermediatesPath string `hcl:"intermediates_path"`
}

type X509PoPPlugin struct {
Expand Down Expand Up @@ -152,8 +155,22 @@ func loadConfigData(config *X509PoPConfig) (*configData, error) {
return nil, fmt.Errorf("x509pop: unable to parse leaf certificate: %v", err)
}

certificates := certificate.Certificate

// Append intermediate certificates if IntermediatesPath is set.
if strings.TrimSpace(config.IntermediatesPath) != "" {
intermediates, err := util.LoadCertificates(config.IntermediatesPath)
if err != nil {
return nil, fmt.Errorf("x509pop: unable to load intermediate certificates: %v", err)
}

for _, cert := range intermediates {
certificates = append(certificates, cert.Raw)
}
}

attestationDataBytes, err := json.Marshal(x509pop.AttestationData{
Certificates: certificate.Certificate,
Certificates: certificates,
})
if err != nil {
return nil, fmt.Errorf("x509pop: unable to marshal attestation data: %v", err)
Expand Down
58 changes: 49 additions & 9 deletions pkg/agent/plugin/nodeattestor/x509pop/x509pop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"

"github.com/spiffe/spire/pkg/common/plugin/x509pop"
"github.com/spiffe/spire/pkg/common/util"
"github.com/spiffe/spire/proto/agent/nodeattestor"
"github.com/spiffe/spire/proto/common/plugin"
"github.com/spiffe/spire/test/fixture"
Expand All @@ -28,24 +29,43 @@ type Suite struct {
}

func (s *Suite) SetupTest() {
require := s.Require()

leafKeyPath := fixture.Join("nodeattestor", "x509pop", "leaf-key.pem")
leafCertPath := fixture.Join("nodeattestor", "x509pop", "leaf-crt-bundle.pem")

s.p = nodeattestor.NewBuiltIn(New())
s.configure(leafKeyPath, leafCertPath, "")
}

func (s *Suite) configure(privateKeyPath, certificatePath, intermediatesPath string) {
require := s.Require()
config := fmt.Sprintf(`
trust_domain = "example.org"
private_key_path = %q
certificate_path = %q`, privateKeyPath, certificatePath)

if intermediatesPath != "" {
config += fmt.Sprintf(`
intermediates_path = %q`, intermediatesPath)
}

resp, err := s.p.Configure(context.Background(), &plugin.ConfigureRequest{
Configuration: fmt.Sprintf(`
trust_domain = "example.org"
private_key_path = %q
certificate_path = %q`, leafKeyPath, leafCertPath),
Configuration: config,
})
require.NoError(err)
require.Equal(resp, &plugin.ConfigureResponse{})

kp, err := tls.LoadX509KeyPair(leafCertPath, leafKeyPath)
kp, err := tls.LoadX509KeyPair(certificatePath, privateKeyPath)
require.NoError(err)
s.leafBundle = kp.Certificate

certificates := kp.Certificate
if intermediatesPath != "" {
certs, err := util.LoadCertificates(intermediatesPath)
require.NoError(err)
for _, c := range certs {
certificates = append(certificates, c.Raw)
}
}

s.leafBundle = certificates
s.leafCert, err = x509.ParseCertificate(s.leafBundle[0])
require.NoError(err)
}
Expand Down Expand Up @@ -93,6 +113,14 @@ func (s *Suite) TestFetchAttestationDataSuccess() {
require.NoError(err)
}

func (s *Suite) TestFetchAttestationDataSuccessWithIntermediates() {
leafKeyPath := fixture.Join("nodeattestor", "x509pop", "leaf-key.pem")
leafCertPath := fixture.Join("nodeattestor", "x509pop", "leaf.pem")
intermediatePath := fixture.Join("nodeattestor", "x509pop", "intermediate.pem")
s.configure(leafKeyPath, leafCertPath, intermediatePath)
s.TestFetchAttestationDataSuccess()
}

func (s *Suite) TestFetchAttestationDataFailure() {
require := s.Require()

Expand Down Expand Up @@ -179,6 +207,18 @@ func (s *Suite) TestConfigure() {
s.errorContains(err, "x509pop: unable to load keypair")
require.Nil(resp)

// cannot load intermediates
leafKeyPath := fixture.Join("nodeattestor", "x509pop", "leaf-key.pem")
leafCertPath := fixture.Join("nodeattestor", "x509pop", "leaf-crt-bundle.pem")
resp, err = s.p.Configure(context.Background(), &plugin.ConfigureRequest{
Configuration: fmt.Sprintf(`
trust_domain = "example.org"
private_key_path = %q
certificate_path = %q
intermediates_path = "blah"`, leafKeyPath, leafCertPath),
})
s.errorContains(err, "x509pop: unable to load intermediate certificates")
require.Nil(resp)
}

func (s *Suite) TestGetPluginInfo() {
Expand Down
12 changes: 11 additions & 1 deletion pkg/common/util/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ func NewCertPool(certs ...*x509.Certificate) *x509.CertPool {
// LoadCertPool loads one or more certificates into an *x509.CertPool from
// a PEM file on disk.
func LoadCertPool(path string) (*x509.CertPool, error) {
certs, err := LoadCertificates(path)
if err != nil {
return nil, err
}
return NewCertPool(certs...), nil
}

// LoadCertificates loads one or more certificates into an []*x509.Certificate from
// a PEM file on disk.
func LoadCertificates(path string) ([]*x509.Certificate, error) {
rest, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
Expand Down Expand Up @@ -48,5 +58,5 @@ func LoadCertPool(path string) (*x509.CertPool, error) {
return nil, errors.New("no certificates found in file")
}

return NewCertPool(certs...), nil
return certs, nil
}
1 change: 0 additions & 1 deletion pkg/server/plugin/nodeattestor/x509pop/x509pop.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"sync"

"github.com/hashicorp/hcl"

"github.com/spiffe/spire/pkg/common/plugin/x509pop"
"github.com/spiffe/spire/pkg/common/util"
spi "github.com/spiffe/spire/proto/common/plugin"
Expand Down
2 changes: 2 additions & 0 deletions test/fixture/nodeattestor/x509pop/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ func main() {

writeKey("leaf-key.pem", leafKey)
writeCerts("leaf-crt-bundle.pem", leafCert, intermediateCert)
writeCerts("leaf.pem", leafCert)
writeCerts("intermediate.pem", intermediateCert)
writeCerts("root-crt.pem", rootCert)
}

Expand Down
9 changes: 9 additions & 0 deletions test/fixture/nodeattestor/x509pop/intermediate.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIBRzCB0qADAgECAgEBMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEwMDAw
MDBaGA85OTk5MTIzMTIzNTk1OVowADB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDA
Gm2bb+E2IKjcS6a2lCpUys5j7ySQIHM19EULD1jjkRT3y2S8dm5jlfQR4UMF6BFq
KuNiEbML5jfEq1IyzmJ6IHuVDxfhxGq24cXSAT308C/ybnOEuSHgVviae8oscZEC
AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAANhAAsnJCCT
BF3HflSMwISuJ3d6CopcV70Pylza79l97DUGoSeSQEorOjLRFkiB9c9M7SZEgYs5
IgbjcwkCLkHjXq2UNFjhe28MNBTdfD6yjE/x6QiAunw01flG0sJPU2xUzQ==
-----END CERTIFICATE-----
27 changes: 14 additions & 13 deletions test/fixture/nodeattestor/x509pop/leaf-crt-bundle.pem
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIBRjCB0aADAgECAgEBMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEwMDAw
MDBaGA85OTk5MTIzMTIzNTk1OVowADB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDG
MXwDlzSkQlwovhDE3qIhtsoASeQvi8zemhBejvXqrYuowcxAgeovF5mGDpLKvFX1
OtdOWLlnjkZ0qgEvhRSzbvocM76rTLvSfJGJubYVPruvm/wtBNoBwLWxTqy5+dcC
AwEAAaMSMBAwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA2EAKZl2l+YE
mzeoVYpG+IyhExlo7ldLJNp7GuvRzvxI0zTWe/wVjw3jfLY2nMHQh4TlkC6JJ6u/
l4OcuHLPY3+1X/w+VKljKGaMvJRuNgQYWjFQtY9RPszXq2TRmR7F+V1x
MIIBYTCB7KADAgECAgEBMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEwMDAw
MDBaGA85OTk5MTIzMTIzNTk1OVowGzEZMBcGA1UEAxMQc29tZSBjb21tb24gbmFt
ZTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDR/rrOq9GhzI9XFxIOxqEZ7hXmc0P9
6CjEi3xl5BQVIkQnx46cHKEY6vyEodxjcv5HefJ3Jmpx+4Jf+J9KJ+XGkiD3T7zC
d7FX0zPyMBxtImvojJDxuqlrUCs0cHBZCP8CAwEAAaMSMBAwDgYDVR0PAQH/BAQD
AgeAMA0GCSqGSIb3DQEBCwUAA2EAjp41GzuQBqEIY7F/8O6VQwwDA4qmtTkbSq0P
jYvfDKTaC2tB/nxlZoHdunx2wb/cvjQ0hmp6an5AioX8aRnSp7CwfgM5sDIb6mXz
0EIobXRibY/E88IK2Ok/JUn4Jlpe
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBRzCB0qADAgECAgEBMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEwMDAw
MDBaGA85OTk5MTIzMTIzNTk1OVowADB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDE
2G6iBSlmCJlpPCMQQqGm7PqQ/xoepXytIQCEBQx1Qy1Lrkd4ctn5JVUy22ddf1sA
A8N57ljZDJ52h58FiAM5ASf/qmf9b/9yvY8ONNdfmAV47mzUWoGmEqStrsGul1EC
AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAANhAKNDcxBJ
Wxt/ptrnKjHNaYzq571BGUppFmIHqfC6kV2tBfVGlc/fxaGVSWJ93HbBzWx7PHvq
7zV4QtOLtMsNB+1qppGM39X6zfx/R73lYvdhJVlH25cJjGY3mtyp6H4Sgg==
MDBaGA85OTk5MTIzMTIzNTk1OVowADB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDA
Gm2bb+E2IKjcS6a2lCpUys5j7ySQIHM19EULD1jjkRT3y2S8dm5jlfQR4UMF6BFq
KuNiEbML5jfEq1IyzmJ6IHuVDxfhxGq24cXSAT308C/ybnOEuSHgVviae8oscZEC
AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAANhAAsnJCCT
BF3HflSMwISuJ3d6CopcV70Pylza79l97DUGoSeSQEorOjLRFkiB9c9M7SZEgYs5
IgbjcwkCLkHjXq2UNFjhe28MNBTdfD6yjE/x6QiAunw01flG0sJPU2xUzQ==
-----END CERTIFICATE-----
22 changes: 11 additions & 11 deletions test/fixture/nodeattestor/x509pop/leaf-key.pem
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
-----BEGIN PRIVATE KEY-----
MIIB5AIBADANBgkqhkiG9w0BAQEFAASCAc4wggHKAgEAAmEAxjF8A5c0pEJcKL4Q
xN6iIbbKAEnkL4vM3poQXo716q2LqMHMQIHqLxeZhg6SyrxV9TrXTli5Z45GdKoB
L4UUs276HDO+q0y70nyRibm2FT67r5v8LQTaAcC1sU6sufnXAgMBAAECYGxT7dHU
mrxRXSgTwvyoJ3w/+acwvB1Uz1S4ZswYXce4tcY2rxpvJ/43av2AB7HyQB7Qgrbm
FZa2jPh7DV4w3+NyO5MeXxfCAuc8PwlwtVdQTZnSF+YbXniB7dFrgCtjyQIxANRW
+KDluhsS8eWfOXD6gt8JC+QOEwoqUBf3fQev/r4jeQQNx9ZrWPBUg67o7gS0ZQIx
AO7x4XC7lQ7kFo3iWk5Uf1/vgNoIigg5XS0fVNR7xWPxxIJvlURNY2Vkkx9lcMn7
iwIxALzGdVPV6JaZSSTzYYXnsOHIkSG2wYaQB5THGgjzlm5D6xqHhdpCpVdES638
t17HYQIwX9G9rwB6ONt8s+8meazm22jnCghMmhmu5M5grUjpEjg8rnXirN4/0sQv
P3LldQobAjAr4TXoZ/xJhYdAg0F0pIOwQhHqUsvKwZ60axsRUFEKx4lftrRFczH/
Q6k0WeCX9vw=
MIIB5QIBADANBgkqhkiG9w0BAQEFAASCAc8wggHLAgEAAmEA0f66zqvRocyPVxcS
DsahGe4V5nND/egoxIt8ZeQUFSJEJ8eOnByhGOr8hKHcY3L+R3nydyZqcfuCX/if
SiflxpIg90+8wnexV9Mz8jAcbSJr6IyQ8bqpa1ArNHBwWQj/AgMBAAECYQCzSfsQ
jR30OISBZM8kEm5lhyLnmK4KUHbOKBFTpQGIcbMjC3w0yTS545cpXlCeEASBLxQ3
3XEQSF3W1SmZBHuI/nMXBG3lc48VkeL8++lSPg08DWaEdzJzG6A0gsEjjuECMQD2
uwDW78B3gW9SP4PUXeRYbo68XoLr28+AIt0Bh07FiMLBsL+7xtkwqM0C7b6PZCkC
MQDZ4mnW0LvVAjjnOQ4SgdWFHZh7fcDQ5s2RvSp3HGFb/ALoRr7yfO10OkMUiTq9
aOcCMQDWHNiQrcSfsMKTZK0ZmVV07JSPoZEJ71o1/4s9LVfNkm44uhLZeKm4UXR/
6yNoumkCMGTD7ljXnhar+W8OFvD+NKZkgpGSHes+4pFlH8+IQ4qL6ThNB6AToKmh
DEbiFFVmvwIwVPiNcKPW9d36K/nM5o41lLcpSvJGneGQQsNDHvZDIiMpCFVvxoBz
fzRRb2sFi1gI
-----END PRIVATE KEY-----
10 changes: 10 additions & 0 deletions test/fixture/nodeattestor/x509pop/leaf.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBYTCB7KADAgECAgEBMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEwMDAw
MDBaGA85OTk5MTIzMTIzNTk1OVowGzEZMBcGA1UEAxMQc29tZSBjb21tb24gbmFt
ZTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDR/rrOq9GhzI9XFxIOxqEZ7hXmc0P9
6CjEi3xl5BQVIkQnx46cHKEY6vyEodxjcv5HefJ3Jmpx+4Jf+J9KJ+XGkiD3T7zC
d7FX0zPyMBxtImvojJDxuqlrUCs0cHBZCP8CAwEAAaMSMBAwDgYDVR0PAQH/BAQD
AgeAMA0GCSqGSIb3DQEBCwUAA2EAjp41GzuQBqEIY7F/8O6VQwwDA4qmtTkbSq0P
jYvfDKTaC2tB/nxlZoHdunx2wb/cvjQ0hmp6an5AioX8aRnSp7CwfgM5sDIb6mXz
0EIobXRibY/E88IK2Ok/JUn4Jlpe
-----END CERTIFICATE-----
12 changes: 6 additions & 6 deletions test/fixture/nodeattestor/x509pop/root-crt.pem
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
-----BEGIN CERTIFICATE-----
MIIBRzCB0qADAgECAgEBMA0GCSqGSIb3DQEBCwUAMAAwIhgPMDAwMTAxMDEwMDAw
MDBaGA85OTk5MTIzMTIzNTk1OVowADB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQC/
i0UJYmB/n2yk0W+UVYOVjOe4PjG7Tx2TfWYGokhsdwXPYCfCG5/BePFyTAhVXtCS
ck7T0s4bXvGFgo7VV6Ewk9hzGRA+R8/Qq7b+xCMi3ToDfN5qWRbTNzWX3X32mgcC
AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAANhAIDqwPNL
8LGGsaq0QKeSU+oaiNb1Eccmiy1ZPpoyzzL8ies5r5z+I21u6fciRUFJqWLN0CWF
FTJXpmsM0QWZMxfIPJyYofdAM7uRVzzsgTSZ6kuIwOEf0rthTJqVsiYTvg==
MDBaGA85OTk5MTIzMTIzNTk1OVowADB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQCf
ha+VM9l0EsNRK7OxQRr7M+sy8KSylfAdN5IxcBCnwiwlvUozWtPMd3rWG0UCGOzm
ipBiLpNZVbXPyvs7O6v303qu4GE+Co/GqN9M40BtK4Wqi78teQywUxbz53GvXOEC
AwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAANhAIYB6ahe
z6IfBSWda+z523bA1RwnMO8e542tGe5EZp/ZzN7JyqRFnZWvw86tVlQwn8pQqHAb
k5m7e2qgCRJcGLvfszo5AweBxGYiVL6o6pH7ZeHjmrGlsilgKgPtV0xntA==
-----END CERTIFICATE-----