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 http node attestor #4909

Merged
merged 56 commits into from
Aug 6, 2024
Merged
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
b322773
Add http challenge node attestor
kfox1111 May 10, 2024
f08d9d2
Fix various issues so it works again after refactor
kfox1111 May 11, 2024
009166f
Fix some issues
kfox1111 May 11, 2024
7caac6f
Fix some issues
kfox1111 May 11, 2024
3e68d07
Fix some issues
kfox1111 May 11, 2024
baaa4f6
Fix some issues
kfox1111 May 11, 2024
029f117
Fix some issues
kfox1111 May 11, 2024
82af10b
Fix some issues
kfox1111 May 11, 2024
86fbf7c
Fix some issues
kfox1111 May 11, 2024
727c5f9
Implement tofu. Incorperate feedback
kfox1111 May 15, 2024
9f42248
Fix some lint bits
kfox1111 May 16, 2024
76d761f
More lint
kfox1111 May 16, 2024
a693947
More lint
kfox1111 May 16, 2024
28dc797
Merge branch 'main' into http
kfox1111 May 16, 2024
6416f01
Merge branch 'main' into http
kfox1111 May 30, 2024
9e8897e
Apply suggestions from code review
kfox1111 Jun 5, 2024
fdfc837
Incorperate feedback
kfox1111 Jun 5, 2024
f8bc768
Merge branch 'http' of https://github.com/kfox1111/spire into http
kfox1111 Jun 5, 2024
b5a439e
Incorperate feedback
kfox1111 Jun 5, 2024
0656513
Incorperate feedback
kfox1111 Jun 5, 2024
6a94dfd
Fix example
kfox1111 Jun 5, 2024
4e8133e
Incorperate feedback
kfox1111 Jun 10, 2024
b0df1d6
Incorperate feedback
kfox1111 Jun 10, 2024
0c1d254
Incorperate feedback
kfox1111 Jun 11, 2024
effb6b3
Fix lint issues
kfox1111 Jun 12, 2024
d6f3b6a
Fix lint issues
kfox1111 Jun 12, 2024
6cdb65b
Fix 404 issue
kfox1111 Jun 17, 2024
98d7363
Fix lint issue
kfox1111 Jun 17, 2024
623ed12
Fix issue with protocol
kfox1111 Jun 18, 2024
968e90e
Merge branch 'main' into http
kfox1111 Jun 18, 2024
0e7dd47
Remove tempate
kfox1111 Jun 22, 2024
b687049
Apply suggestions from code review
kfox1111 Jun 22, 2024
1caaaec
Merge branch 'main' into http
kfox1111 Jun 22, 2024
069bb2b
Fix typo
kfox1111 Jun 22, 2024
69edbe1
Add some unit tests
kfox1111 Jun 24, 2024
41f1e74
Add a bunch of httpchallenge server plugin tests
kfox1111 Jul 16, 2024
92e72d5
Add some more tests
kfox1111 Jul 16, 2024
151d3c3
Test server works
kfox1111 Jul 17, 2024
b6c4a41
Add tofu checks
kfox1111 Jul 17, 2024
f00d02f
Add httpchallenge agent tests
kfox1111 Jul 19, 2024
81b205a
Incorperate feedback
kfox1111 Jul 19, 2024
501a957
gofmt files
kfox1111 Jul 19, 2024
a404aa3
Apply suggestions from code review
kfox1111 Jul 19, 2024
5ab497d
Fix lint issues
kfox1111 Jul 19, 2024
b5caee3
Fix lint issues
kfox1111 Jul 19, 2024
1af2187
Fix test
kfox1111 Jul 19, 2024
a2c0385
Incorperate feedback. Add localhost block.
kfox1111 Jul 20, 2024
be2b414
Fix test
kfox1111 Jul 20, 2024
2bec5df
Add test for localhost test. Incorperate feedback
kfox1111 Jul 20, 2024
4c95d25
Incorperate feedback
kfox1111 Jul 20, 2024
2ac078f
Fix lint issue
kfox1111 Jul 20, 2024
32f8f04
Merge branch 'main' into http
kfox1111 Jul 20, 2024
f47af5c
Merge branch 'main' into http
kfox1111 Jul 23, 2024
f596796
Update doc/plugin_server_nodeattestor_http_challenge.md
kfox1111 Aug 5, 2024
2880654
Merge branch 'main' into http
kfox1111 Aug 5, 2024
3dae7a2
Incorperate feedback
kfox1111 Aug 5, 2024
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
209 changes: 209 additions & 0 deletions pkg/agent/plugin/nodeattestor/httpchallenge/httpchallenge_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
//go:build !darwin

package httpchallenge_test

import (
"context"
"encoding/json"
"errors"
"fmt"
"net"
"testing"

configv1 "github.com/spiffe/spire-plugin-sdk/proto/spire/service/common/config/v1"
"github.com/spiffe/spire/pkg/agent/plugin/nodeattestor"
nodeattestortest "github.com/spiffe/spire/pkg/agent/plugin/nodeattestor/test"
"github.com/spiffe/spire/pkg/agent/plugin/nodeattestor/httpchallenge"
common_httpchallenge "github.com/spiffe/spire/pkg/common/plugin/httpchallenge"
"github.com/spiffe/spire/test/plugintest"
"github.com/stretchr/testify/require"
)
var (
streamBuilder = nodeattestortest.ServerStream("http_challenge")
)

func TestConfigureCommon(t *testing.T) {
tests := []struct {
name string
hclConf string
expErr string
}{
{
name: "Configure fails if receives wrong HCL configuration",
hclConf: "not HCL conf",
expErr: "rpc error: code = InvalidArgument desc = unable to decode configuration",
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
plugin := httpchallenge.New()

resp, err := plugin.Configure(context.Background(), &configv1.ConfigureRequest{HclConfiguration: tt.hclConf})
if tt.expErr != "" {
require.Contains(t, err.Error(), tt.expErr)
require.Nil(t, resp)
return
}

require.NoError(t, err)
require.NotNil(t, resp)
})
}
}

func TestAidAttestationFailures(t *testing.T) {
tests := []struct {
name string
config string
expErr string
serverStream nodeattestor.ServerStream
}{
{
name: "AidAttestation fails if server does not sends a challenge",
config: "",
expErr: "the error",
serverStream: streamBuilder.FailAndBuild(errors.New("the error")),
},
{
name: "AidAttestation fails if agent cannot unmarshall server challenge",
kfox1111 marked this conversation as resolved.
Show resolved Hide resolved
config: "",
expErr: "rpc error: code = Internal desc = nodeattestor(http_challenge): unable to unmarshal challenge: invalid character 'o' in literal null (expecting 'u')",
serverStream: streamBuilder.IgnoreThenChallenge([]byte("not-a-challenge")).Build(),
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
var err error
p := loadAndConfigurePlugin(t, tt.config)

err = p.Attest(context.Background(), tt.serverStream)
if tt.expErr != "" {
require.Contains(t, err.Error(), tt.expErr)
return
}
require.NoError(t, err)
})
}
}

func TestAidAttestationSucceeds(t *testing.T) {
port := 9998
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
kfox1111 marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(t, err)
defer l.Close()

tests := []struct {
name string
config string
attestationData common_httpchallenge.AttestationData
serverStream func(attestationData *common_httpchallenge.AttestationData, challenge []byte, expectPayload []byte, challengeobj *common_httpchallenge.Challenge) nodeattestor.ServerStream
}{
{
name: "Check for random port",
config: "",
attestationData: common_httpchallenge.AttestationData{
HostName: "spire-dev",
AgentName: "default",
},
serverStream: func(attestationData *common_httpchallenge.AttestationData, challenge []byte, expectPayload []byte, challengeobj *common_httpchallenge.Challenge) nodeattestor.ServerStream{
return streamBuilder.
Handle(func(challenge []byte) ([]byte, error) {
attestationData := new(common_httpchallenge.AttestationData)
if err := json.Unmarshal(challenge, attestationData); err != nil {
return nil, err
}
if attestationData.Port == 9998 {
return nil, errors.New("Random port failed.")

Check failure on line 119 in pkg/agent/plugin/nodeattestor/httpchallenge/httpchallenge_test.go

View workflow job for this annotation

GitHub Actions / lint (linux)

error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)

Check failure on line 119 in pkg/agent/plugin/nodeattestor/httpchallenge/httpchallenge_test.go

View workflow job for this annotation

GitHub Actions / lint (windows)

error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
}
return nil, nil
}).Build()
},
},
{
name: "Check for advertised port",
config: "advertised_port = 9998",
attestationData: common_httpchallenge.AttestationData{
HostName: "spire-dev",
AgentName: "default",
},
serverStream: func(attestationData *common_httpchallenge.AttestationData, challenge []byte, expectPayload []byte, challengeobj *common_httpchallenge.Challenge) nodeattestor.ServerStream{
return streamBuilder.
Handle(func(challenge []byte) ([]byte, error) {
attestationData := new(common_httpchallenge.AttestationData)
if err := json.Unmarshal(challenge, attestationData); err != nil {
return nil, err
}
if attestationData.Port != 9998 {
return nil, errors.New("Advertised port failed.")

Check failure on line 140 in pkg/agent/plugin/nodeattestor/httpchallenge/httpchallenge_test.go

View workflow job for this annotation

GitHub Actions / lint (linux)

error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)

Check failure on line 140 in pkg/agent/plugin/nodeattestor/httpchallenge/httpchallenge_test.go

View workflow job for this annotation

GitHub Actions / lint (windows)

error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
}
return nil, nil
}).Build()
},
},
{
name: "Test with defaults except port",
config: "port=9999",
attestationData: common_httpchallenge.AttestationData{
HostName: "spire-dev",
AgentName: "default",
Port: 9999,
},
serverStream: func(attestationData *common_httpchallenge.AttestationData, challenge []byte, expectPayload []byte, challengeobj *common_httpchallenge.Challenge) nodeattestor.ServerStream{
return streamBuilder.ExpectThenChallenge(expectPayload, challenge).
Handle(func(challengeResponse []byte) ([]byte, error) {
err := common_httpchallenge.VerifyChallenge(attestationData, challengeobj)
return nil, err
}).Build()
},
},
{
name: "Test with all the settings",
config: "hostname=\"localhost\"\nagentname=\"test\"\nport=9999\nadvertised_port=9999",
attestationData: common_httpchallenge.AttestationData{
HostName: "localhost",
AgentName: "test",
Port: 9999,
},
serverStream: func(attestationData *common_httpchallenge.AttestationData, challenge []byte, expectPayload []byte, challengeobj *common_httpchallenge.Challenge) nodeattestor.ServerStream{
return streamBuilder.ExpectThenChallenge(expectPayload, challenge).
Handle(func(challengeResponse []byte) ([]byte, error) {
err := common_httpchallenge.VerifyChallenge(attestationData, challengeobj)
return nil, err
}).Build()
},
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
var err error
expectPayload, err := json.Marshal(&tt.attestationData)
require.NoError(t, err)

challengeobj, err := common_httpchallenge.GenerateChallenge()
require.NoError(t, err)

challenge, err := json.Marshal(challengeobj)
require.NoError(t, err)

p := loadAndConfigurePlugin(t, tt.config)

err = p.Attest(context.Background(), tt.serverStream(&tt.attestationData, challenge, expectPayload, challengeobj))
require.NoError(t, err)
})
}
}

func loadAndConfigurePlugin(t *testing.T, config string) nodeattestor.NodeAttestor {
return loadPlugin(t, plugintest.Configure(config))
}

func loadPlugin(t *testing.T, options ...plugintest.Option) nodeattestor.NodeAttestor {
na := new(nodeattestor.V1)
plugintest.Load(t, httpchallenge.BuiltIn(), na, options...)
return na
}
Loading