From a36abf4b3a1b34b33d5416797771396a6ff874ec Mon Sep 17 00:00:00 2001 From: Brooke Bryan Date: Tue, 18 Jul 2017 21:11:30 +0100 Subject: [PATCH] Support for roles --- README.md | 2 +- keys/keys.go | 7 +++++++ portcullis.go | 26 +++++++++++++++++++++++++- portcullis_test.go | 17 +++++++++++++++-- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 07983c3..90cd154 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Portcullis Go Library #### Usage FromContext() accepts the context from your GRPC request ```go -import "github.com/cubex/portcullis-go" +import "github.com/kubex/portcullis-go" project := portcullis.FromContext(ctx).ProjectID ``` diff --git a/keys/keys.go b/keys/keys.go index 2b6316a..e86d080 100644 --- a/keys/keys.go +++ b/keys/keys.go @@ -14,6 +14,8 @@ const ( firstNameKey = "first-name" lastNameKey = "last-name" + + rolesKey = "roles" ) // GetKeyPrefix returns portcullis key prefix @@ -61,6 +63,11 @@ func GetLastNameKey() string { return keyprefix + lastNameKey } +// GetRolesKey key for retrieving roles from the request +func GetRolesKey() string { + return keyprefix + rolesKey +} + // GetGenericKeyForString retrieves key for given generic value func GetGenericKeyForString(in string) string { key := strings.Replace(in, " ", "-", -1) diff --git a/portcullis.go b/portcullis.go index 174548a..5944aba 100644 --- a/portcullis.go +++ b/portcullis.go @@ -11,7 +11,7 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc/metadata" - "github.com/cubex/portcullis-go/keys" + "github.com/kubex/portcullis-go/keys" ) // ReqInfo is the structure for deserialised request information @@ -25,6 +25,7 @@ type ReqInfo struct { LastName string signature string meta metadata.MD + Roles []string } // Verify checks that the request signature matches using signature key @@ -60,6 +61,16 @@ func (r *ReqInfo) GlobalAppID() string { return fmt.Sprintf("%s/%s", r.VendorID, r.AppID) } +// HasRole check if the user has a specific role +func (r *ReqInfo) HasRole(checkRole string) bool { + for _, role := range r.Roles { + if role == checkRole { + return true + } + } + return false +} + // FromContext retrieves request info from given request context func FromContext(ctx context.Context) ReqInfo { md, _ := metadata.FromContext(ctx) @@ -72,6 +83,7 @@ func FromContext(ctx context.Context) ReqInfo { AppID: safeGetMetaValString(keys.GetAppIDKey(), md), VendorID: safeGetMetaValString(keys.GetAppVendorKey(), md), signature: safeGetMetaValString(keys.GetSignatureKey(), md), + Roles: safeGetMetaValStringSlice(keys.GetRolesKey(), md), meta: md, } return res @@ -86,3 +98,15 @@ func safeGetMetaValString(key string, md metadata.MD) string { } return result } + +func safeGetMetaValStringSlice(key string, md metadata.MD) []string { + result := []string{} + if md != nil { + if sliceKeys, hasKey := md[key]; hasKey { + for _, sliceValue := range sliceKeys { + result = append(result, sliceValue) + } + } + } + return result +} diff --git a/portcullis_test.go b/portcullis_test.go index 52aae8e..55a9ca7 100644 --- a/portcullis_test.go +++ b/portcullis_test.go @@ -7,8 +7,8 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc/metadata" - "github.com/cubex/portcullis-go" - "github.com/cubex/portcullis-go/keys" + "github.com/kubex/portcullis-go" + "github.com/kubex/portcullis-go/keys" ) const ( @@ -30,6 +30,10 @@ func TestAuthDataExtraction(t *testing.T) { metamap[keys.GetAppVendorKey()] = testVendor meta := metadata.New(metamap) + + meta[keys.GetRolesKey()] = append(meta[keys.GetRolesKey()], "role2") + meta[keys.GetRolesKey()] = append(meta[keys.GetRolesKey()], "role1") + ctx := metadata.NewContext(context.Background(), meta) in := portcullis.FromContext(ctx) @@ -37,6 +41,10 @@ func TestAuthDataExtraction(t *testing.T) { t.Error("Global app ID does not contain expected value") } + if !in.HasRole("role1") || !in.HasRole("role2") { + t.Error("Roles do not contain expected values") + } + if in.ProjectID != testProject { t.Error("Project does not contain expected value") } @@ -60,6 +68,7 @@ func TestAuthDataExtractionWithMissingFields(t *testing.T) { project := portcullis.FromContext(ctx).ProjectID username := portcullis.FromContext(ctx).Username userID := portcullis.FromContext(ctx).UserID + roles := portcullis.FromContext(ctx).Roles if username != testUsername { t.Error("Username does not contain expected value") @@ -72,6 +81,10 @@ func TestAuthDataExtractionWithMissingFields(t *testing.T) { if userID != "" { t.Error("userID does not contain expected value") } + + if len(roles) != 0 { + t.Error("roles do not contain expected value") + } } // TestExtractionWithInvalidContext tests extraction result with context contains no metadata