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

Prevent to change Server's trust domain #644

Merged
merged 13 commits into from Dec 19, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 17 additions & 1 deletion pkg/server/plugin/datastore/sql/sql.go
Expand Up @@ -647,6 +647,16 @@ func fetchAttestedNode(tx *gorm.DB, req *datastore.FetchAttestedNodeRequest) (*d
}

func listAttestedNodes(tx *gorm.DB, req *datastore.ListAttestedNodesRequest) (*datastore.ListAttestedNodesResponse, error) {
p := req.Pagination
var err error
if p != nil && p.PageSize > 0 {
tx, err = applyPagination(p, tx)

if err != nil {
return nil, err
}
}

if req.ByExpiresBefore != nil {
tx = tx.Where("expires_at < ?", time.Unix(req.ByExpiresBefore.Value, 0))
}
Expand All @@ -656,8 +666,14 @@ func listAttestedNodes(tx *gorm.DB, req *datastore.ListAttestedNodesRequest) (*d
return nil, sqlError.Wrap(err)
}

if p != nil && p.PageSize > 0 && len(models) > 0 {
lastEntry := (models)[len(models)-1]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: () on (models) is unnecessary

p.Token = fmt.Sprint(lastEntry.ID)
}

resp := &datastore.ListAttestedNodesResponse{
Nodes: make([]*datastore.AttestedNode, 0, len(models)),
Nodes: make([]*datastore.AttestedNode, 0, len(models)),
Pagination: p,
}

for _, model := range models {
Expand Down
182 changes: 182 additions & 0 deletions pkg/server/plugin/datastore/sql/sql_test.go
Expand Up @@ -244,6 +244,188 @@ func (s *PluginSuite) TestFetchStaleNodes() {
s.Equal([]*datastore.AttestedNode{epast}, sresp.Nodes)
}

func (s *PluginSuite) TestFetchAttestedNodesWithPagination() {
// Create all necessary nodes
aNode1 := &datastore.AttestedNode{
SpiffeId: "node1",
AttestationDataType: "aws-tag",
CertSerialNumber: "badcafe",
CertNotAfter: time.Now().Add(-time.Hour).Unix(),
}

aNode2 := &datastore.AttestedNode{
SpiffeId: "node2",
AttestationDataType: "aws-tag",
CertSerialNumber: "deadbeef",
CertNotAfter: time.Now().Add(time.Hour).Unix(),
}

aNode3 := &datastore.AttestedNode{
SpiffeId: "node3",
AttestationDataType: "aws-tag",
CertSerialNumber: "badcafe",
CertNotAfter: time.Now().Add(-time.Hour).Unix(),
}

aNode4 := &datastore.AttestedNode{
SpiffeId: "node4",
AttestationDataType: "aws-tag",
CertSerialNumber: "badcafe",
CertNotAfter: time.Now().Add(-time.Hour).Unix(),
}

_, err := s.ds.CreateAttestedNode(ctx, &datastore.CreateAttestedNodeRequest{Node: aNode1})
s.Require().NoError(err)

_, err = s.ds.CreateAttestedNode(ctx, &datastore.CreateAttestedNodeRequest{Node: aNode2})
s.Require().NoError(err)

_, err = s.ds.CreateAttestedNode(ctx, &datastore.CreateAttestedNodeRequest{Node: aNode3})
s.Require().NoError(err)

_, err = s.ds.CreateAttestedNode(ctx, &datastore.CreateAttestedNodeRequest{Node: aNode4})
s.Require().NoError(err)

tests := []struct {
name string
pagination *datastore.Pagination
byExpiresBefore *wrappers.Int64Value
expectedList []*datastore.AttestedNode
expectedPagination *datastore.Pagination
}{
{
name: "pagination_without_token",
pagination: &datastore.Pagination{
PageSize: 2,
},
expectedList: []*datastore.AttestedNode{aNode1, aNode2},
expectedPagination: &datastore.Pagination{
Token: "2",
PageSize: 2,
},
},
{
name: "pagination_not_null_but_page_size_is_zero",
pagination: &datastore.Pagination{
Token: "0",
PageSize: 0,
},
expectedList: []*datastore.AttestedNode{aNode1, aNode2, aNode3, aNode4},
expectedPagination: &datastore.Pagination{
Token: "0",
PageSize: 0,
},
},
{
name: "get_all_nodes_first_page",
pagination: &datastore.Pagination{
Token: "0",
PageSize: 2,
},
expectedList: []*datastore.AttestedNode{aNode1, aNode2},
expectedPagination: &datastore.Pagination{
Token: "2",
PageSize: 2,
},
},
{
name: "get_all_nodes_second_page",
pagination: &datastore.Pagination{
Token: "2",
PageSize: 2,
},
expectedList: []*datastore.AttestedNode{aNode3, aNode4},
expectedPagination: &datastore.Pagination{
Token: "4",
PageSize: 2,
},
},
{
name: "get_all_nodes_third_page_no_results",
expectedList: []*datastore.AttestedNode{},
pagination: &datastore.Pagination{
Token: "4",
PageSize: 2,
},
expectedPagination: &datastore.Pagination{
Token: "4",
PageSize: 2,
},
},
{
name: "get_nodes_by_expire_before_get_only_page_fist_page",
pagination: &datastore.Pagination{
Token: "0",
PageSize: 2,
},
byExpiresBefore: &wrappers.Int64Value{
Value: time.Now().Unix(),
},
expectedList: []*datastore.AttestedNode{aNode1, aNode3},
expectedPagination: &datastore.Pagination{
Token: "3",
PageSize: 2,
},
},
{
name: "get_nodes_by_expire_before_get_only_page_second_page",
pagination: &datastore.Pagination{
Token: "3",
PageSize: 2,
},
byExpiresBefore: &wrappers.Int64Value{
Value: time.Now().Unix(),
},
expectedList: []*datastore.AttestedNode{aNode4},
expectedPagination: &datastore.Pagination{
Token: "4",
PageSize: 2,
},
},
{
name: "get_nodes_by_expire_before_get_only_page_third_page_no_resultds",
pagination: &datastore.Pagination{
Token: "4",
PageSize: 2,
},
byExpiresBefore: &wrappers.Int64Value{
Value: time.Now().Unix(),
},
expectedList: []*datastore.AttestedNode{},
expectedPagination: &datastore.Pagination{
Token: "4",
PageSize: 2,
},
},
}
for _, test := range tests {
s.T().Run(test.name, func(t *testing.T) {
resp, err := s.ds.ListAttestedNodes(ctx, &datastore.ListAttestedNodesRequest{
ByExpiresBefore: test.byExpiresBefore,
Pagination: test.pagination,
})
require.NoError(t, err)
require.NotNil(t, resp)

expectedResponse := &datastore.ListAttestedNodesResponse{
Nodes: test.expectedList,
Pagination: test.expectedPagination,
}
require.Equal(t, expectedResponse, resp)
})
}

// with invalid token
resp, err := s.ds.ListAttestedNodes(ctx, &datastore.ListAttestedNodesRequest{
Pagination: &datastore.Pagination{
Token: "invalid int",
PageSize: 10,
},
})
s.Require().Nil(resp)
s.Require().Error(err, "could not parse token 'invalid int'")
}

func (s *PluginSuite) TestUpdateAttestedNode() {
node := &datastore.AttestedNode{
SpiffeId: "foo",
Expand Down
49 changes: 22 additions & 27 deletions pkg/server/server.go
Expand Up @@ -37,7 +37,7 @@ const (
invalidSpiffeIDRegistrationEntry = "registration entry with id %v is malformed because invalid SPIFFE ID: %v"
invalidSpiffeIDAttestedNode = "could not parse SPIFFE ID %v, from attested node: %v"

pageSize = 10
pageSize = 1
)

type Config struct {
Expand Down Expand Up @@ -292,39 +292,34 @@ func (s *Server) caCertsPath() string {
func (s *Server) validateTrustDomain(ctx context.Context, ds datastore.DataStore) error {
trustDomain := s.config.TrustDomain.Host

var token string
// Repeat until no more results are returned
for {
fetchResponse, err := ds.ListRegistrationEntries(ctx, &datastore.ListRegistrationEntriesRequest{
Pagination: &datastore.Pagination{
Token: token,
PageSize: pageSize,
}})
// Get only first page with a single element
fetchResponse, err := ds.ListRegistrationEntries(ctx, &datastore.ListRegistrationEntriesRequest{
Pagination: &datastore.Pagination{
Token: "",
PageSize: pageSize,
}})

if err != nil {
return err
}
if err != nil {
return err
}

// no entries, finish iteration
if len(fetchResponse.Entries) == 0 {
break
for _, entry := range fetchResponse.Entries {
id, err := url.Parse(entry.SpiffeId)
if err != nil {
return fmt.Errorf(invalidSpiffeIDRegistrationEntry, entry.EntryId, err)
}

for _, entry := range fetchResponse.Entries {
id, err := url.Parse(entry.SpiffeId)
if err != nil {
return fmt.Errorf(invalidSpiffeIDRegistrationEntry, entry.EntryId, err)
}

if id.Host != trustDomain {
return fmt.Errorf(invalidTrustDomainRegistrationEntry, id.Host, trustDomain)
}
if id.Host != trustDomain {
return fmt.Errorf(invalidTrustDomainRegistrationEntry, id.Host, trustDomain)
}

token = fetchResponse.Pagination.Token
}

nodesResponse, err := ds.ListAttestedNodes(ctx, &datastore.ListAttestedNodesRequest{})
// Get only first page with a single element
nodesResponse, err := ds.ListAttestedNodes(ctx, &datastore.ListAttestedNodesRequest{
Pagination: &datastore.Pagination{
Token: "",
PageSize: pageSize,
}})
if err != nil {
return err
}
Expand Down
2 changes: 2 additions & 0 deletions proto/server/datastore/README_pb.md
Expand Up @@ -1017,6 +1017,7 @@ Represents a type with a list of Selector.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| by_expires_before | [.google.protobuf.Int64Value](#spire.server.datastore..google.protobuf.Int64Value) | | |
| pagination | [Pagination](#spire.server.datastore.Pagination) | | |



Expand All @@ -1032,6 +1033,7 @@ Represents a type with a list of Selector.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| nodes | [AttestedNode](#spire.server.datastore.AttestedNode) | repeated | |
| pagination | [Pagination](#spire.server.datastore.Pagination) | | |



Expand Down