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

Conversation

MarcosDY
Copy link
Collaborator

Validate Server's trust domain using persisted attestation nodes and registration entries

…t domains

Signed-off-by: Marcos Yacob <marcos@scytale.io>
Signed-off-by: Marcos Yacob <marcos@scytale.io>
@@ -26,9 +26,22 @@ import (
"github.com/spiffe/spire/pkg/server/svid"
"google.golang.org/grpc"

"errors"

"github.com/spiffe/spire/proto/server/datastore"
Copy link
Member

Choose a reason for hiding this comment

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

nit: looks like these imports ended up in the wrong place

const (
invalidTrustDomainAttestedNode = "An attested node with trust domain '%v' has been detected, " +
"which does not match the configured trust domain of '%v'. If you want to change the trust domain, " +
"please delete all existing attested nodes"
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is currently possible? #27 is related

fetchResponse, err := ds.ListRegistrationEntries(ctx, &datastore.ListRegistrationEntriesRequest{})
if err != nil {
s.config.Log.Error(err)
return errors.New("error trying to fetch entries")
Copy link
Member

Choose a reason for hiding this comment

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

Why not return the error here instead of logging it and returning a different one? Or something like this

return fmt.Errorf("check existing entries: %v", err)

func (s *Server) validateTrustDomain(ctx context.Context, ds datastore.DataStore) error {
trustDomain := s.config.TrustDomain.Host

fetchResponse, err := ds.ListRegistrationEntries(ctx, &datastore.ListRegistrationEntriesRequest{})
Copy link
Member

Choose a reason for hiding this comment

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

I think this will be problematic for production deployments, since we will be scanning the whole table every time we start/restart... we should add a pagination option or something (perhaps as part of a separate PR/Issue?)

func validateSpiffeId(spiffeId string, trustDomain string, errMsg string) error {
id, err := url.Parse(spiffeId)
if err != nil {
return fmt.Errorf("could not parse SPIFFE ID: %v", err)
Copy link
Member

Choose a reason for hiding this comment

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

it would be good if we could include more information here... that it is a registration entry that is bad, and perhaps the entry ID so the user can inspect it/delete it

…s a node with different trust domain

Signed-off-by: Marcos Yacob <marcos@scytale.io>
Signed-off-by: Marcos Yacob <marcos@scytale.io>
Signed-off-by: Marcos Yacob <marcos@scytale.io>
@@ -189,14 +189,21 @@ message BySelectors {
MatchBehavior match = 2;
}

message Pagination {
uint32 token = 1;
Copy link
Member

Choose a reason for hiding this comment

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

i think a string "token" is more flexible... what do others think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agree that was my first approach too

Copy link
Member

Choose a reason for hiding this comment

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

My only gripe is that the sql plugin code is a little pointier when this is a string because we have to convert it and check for errors in a spot that would otherwise be error-free

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes, I added a parser, to prevent it to happens, basically parse to int and put that int into select, and an error is returned in case parse is not valid

if err := entryTx.Where(entryIDs).Find(&models).Error; err != nil {
return nil, sqlError.Wrap(err)
db := entryTx.Where(entryIDs)
if err := findRegisteredEntries(req, db, &models); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

i think this is less confusing with a functional approach:

models, pagination, err := findRegisteredEntries(db, req.Pagination)
if err != nil {

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

}

// update pagination token based in last result in returned list
func updatePaginationToken(p *datastore.Pagination, entries *[]RegisteredEntry) {
Copy link
Member

Choose a reason for hiding this comment

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

it's seems weird to take a pointer to a slice...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

"io/ioutil"
"net/url"
"os"
"testing"

"fmt"
Copy link
Member

Choose a reason for hiding this comment

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

"fmt" and "bytes" should be grouped with the rest of the std imports

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

@@ -347,6 +347,19 @@ func (s *DataStore) ListRegistrationEntries(ctx context.Context,
s.mu.Lock()
defer s.mu.Unlock()

// no pagination allow for this fake, for now it return only one page
Copy link
Member

Choose a reason for hiding this comment

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

should we implement pagination in the fake datastore so the server startup code that paginates entries for trust domain validation can be tested?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

added

trustDomain := s.config.TrustDomain.Host

var token string
// Repeat until no more results are returned
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need to iterate over all the entries... perhaps we just make the request with PageSize 1 and call it a day? Same for attested nodes

@@ -189,14 +189,21 @@ message BySelectors {
MatchBehavior match = 2;
}

message Pagination {
uint32 token = 1;
Copy link
Member

Choose a reason for hiding this comment

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

My only gripe is that the sql plugin code is a little pointier when this is a string because we have to convert it and check for errors in a spot that would otherwise be error-free

azdagron
azdagron previously approved these changes Dec 19, 2018
@@ -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

Signed-off-by: Marcos Yacob <marcos@scytale.io>
@MarcosDY MarcosDY merged commit 0776a9b into spiffe:master Dec 19, 2018
@MarcosDY MarcosDY deleted the validate-trustdomain-when-starting branch December 19, 2018 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants