From 8c7839bec92feec909b8b36f3d48f394c1ed4675 Mon Sep 17 00:00:00 2001 From: Antoine Date: Wed, 20 May 2020 18:27:17 -0700 Subject: [PATCH] new/tokenutils: added ExtractRestrictions (#73) * new/tokenutils: added ExtractRestrictions * fixed: use new gaia api --- tokenutils/tokenutils.go | 56 +++++++++++++ tokenutils/tokenutils_test.go | 148 ++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) diff --git a/tokenutils/tokenutils.go b/tokenutils/tokenutils.go index 6283c09..ee515e4 100644 --- a/tokenutils/tokenutils.go +++ b/tokenutils/tokenutils.go @@ -112,3 +112,59 @@ func ExtractQuota(token string) (int, error) { return int(q), nil } + +// ExtractRestrictions extracts the eventual authz restrictions embded in the token. +func ExtractRestrictions(token string) (ns string, perms []string, networks []string, err error) { + + claims, err := UnsecureClaimsMap(token) + if err != nil { + return "", nil, nil, err + } + + restrictions, ok := claims["restrictions"].(map[string]interface{}) + if !ok { + return "", nil, nil, nil + } + + lns, ok := restrictions["namespace"] + if ok { + ns, ok = lns.(string) + if !ok { + return "", nil, nil, fmt.Errorf("invalid restrictions.namespace claim type") + } + } + + lai, ok := restrictions["perms"] + if ok { + permsIface, ok := lai.([]interface{}) + if !ok { + return "", nil, nil, fmt.Errorf("invalid restrictions.permissions claim type") + } + + for _, perm := range permsIface { + pstr, ok := perm.(string) + if !ok { + return "", nil, nil, fmt.Errorf("invalid restrictions.permissions claim item type") + } + perms = append(perms, pstr) + } + } + + lnet, ok := restrictions["networks"] + if ok { + lnetIface, ok := lnet.([]interface{}) + if !ok { + return "", nil, nil, fmt.Errorf("invalid restrictions.networks claim type") + } + + for _, net := range lnetIface { + nstr, ok := net.(string) + if !ok { + return "", nil, nil, fmt.Errorf("invalid restrictions.networks claim item type") + } + networks = append(networks, nstr) + } + } + + return ns, perms, networks, nil +} diff --git a/tokenutils/tokenutils_test.go b/tokenutils/tokenutils_test.go index 49f8a23..edae350 100644 --- a/tokenutils/tokenutils_test.go +++ b/tokenutils/tokenutils_test.go @@ -13,6 +13,7 @@ package tokenutils import ( "errors" + "reflect" "testing" . "github.com/smartystreets/goconvey/convey" @@ -316,3 +317,150 @@ func TestExtractQuota(t *testing.T) { }) } } + +func TestExtractRestrictions(t *testing.T) { + type args struct { + token string + } + tests := []struct { + name string + args args + wantNs string + wantPerms []string + wantNets []string + wantErr bool + }{ + { + "valid token with no restrictions", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJleHAiOjE1OTAwMTUzNTIsImlhdCI6MTU4OTkyNTM1MiwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQ0MyIsInN1YiI6ImFwb211eCJ9.agqImtfkfjJugJH59XfQwkasIayYtvG6tz3p84jMulfbgwZzTLzgfRDLNIcfnfqfUix_702BUJxvdlsaSsgeUg`, + }, + "", + nil, + nil, + false, + }, + + { + "valid token with namespace restriction", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsibmFtZXNwYWNlIjoiL3Rlc3QifSwiZXhwIjoxNTkwMDE1MzY2LCJpYXQiOjE1ODk5MjUzNjYsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0NDMiLCJzdWIiOiJhcG9tdXgifQ.3xYCsLm6FuIUnYKE3GPYqrB9-GhUTDUETSuk6hWy8DqnK8DOj95AXWbJsKN7yUSpBp8CuPmbrPRAljnOSROIJg`, + }, + "/test", + nil, + nil, + false, + }, + { + "valid token with invalid namespace restriction", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsibmFtZXNwYWNlIjoxfSwiZXhwIjoxNTkwMDE1MzY2LCJpYXQiOjE1ODk5MjUzNjYsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0NDMiLCJzdWIiOiJhcG9tdXgifQ.dIsnGMSEy961FqXgJH-TBVw8_9VrzH_j4xcQJG4JY0--ekwNuMpLr0CyOJFj_XFuVsY-ZS8Lwj5yJCYHv7TS8Q`, + }, + "", + nil, + nil, + true, + }, + + { + "valid token with permissions restriction", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsicGVybXMiOlsiQGF1dGg6cm9sZT10ZXN0Il19LCJleHAiOjE1OTAwMTUzOTIsImlhdCI6MTU4OTkyNTM5MiwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQ0MyIsInN1YiI6ImFwb211eCJ9.ZgFBGxiU5F_ImSZMy8BwwyOv-1dnDw1z4zY5spUqxSKAzCrtrr_G0FomsL-w0CZOKWDv2Hs99FQPxIRRjfSwSQ`, + }, + "", + []string{"@auth:role=test"}, + nil, + false, + }, + { + "valid token with invalid permissions restriction", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsicGVybXMiOiJAYXV0aDpyb2xlPXRlc3QifSwiZXhwIjoxNTkwMDE1MzkyLCJpYXQiOjE1ODk5MjUzOTIsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0NDMiLCJzdWIiOiJhcG9tdXgifQ.zBBcocIRkBUzcHGUKQk6ywitqMFe9sQsyMRp2raVyuBW0jirIR-yUybXGtOuw8YucCq8uIvC9CPHXUPww6kGtA`, + }, + "", + nil, + nil, + true, + }, + { + "valid token with invalid permissions restriction item type", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsicGVybXMiOlsiQGF1dGg6cm9sZT10ZXN0IiwgMV19LCJleHAiOjE1OTAwMTUzOTIsImlhdCI6MTU4OTkyNTM5MiwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQ0MyIsInN1YiI6ImFwb211eCJ9.zBBcocIRkBUzcHGUKQk6ywitqMFe9sQsyMRp2raVyuBW0jirIR-yUybXGtOuw8YucCq8uIvC9CPHXUPww6kGtA`, + }, + "", + nil, + nil, + true, + }, + + { + "valid token with networks restriction", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsibmV0d29ya3MiOlsiMTI3LjAuMC4xLzMyIl19LCJleHAiOjE1OTAwNDMyMDUsImlhdCI6MTU4OTk1MzIwNSwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQ0MyIsInN1YiI6ImFwb211eCJ9.aO-D-1e7XX18ZGGi2FoKl-lfpc8xBzShrPVHZzLHqXd22ojZEWxKOVaIh8ZVyjs8KWBu-CmCKBCi3eg875j_1A`, + }, + "", + nil, + []string{"127.0.0.1/32"}, + false, + }, + { + "valid token with invalid networks restriction", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsibmV0d29ya3MiOiIxMjcuMC4wLjEvMzIifSwiZXhwIjoxNTkwMDQzMjA1LCJpYXQiOjE1ODk5NTMyMDUsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjQ0NDMiLCJzdWIiOiJhcG9tdXgifQ.dIsnGMSEy961FqXgJH-TBVw8_9VrzH_j4xcQJG4JY0--ekwNuMpLr0CyOJFj_XFuVsY-ZS8Lwj5yJCYHv7TS8Q`, + }, + "", + nil, + nil, + true, + }, + { + "valid token with invalid networks restriction item", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsibmV0d29ya3MiOlsxXX0sImV4cCI6MTU5MDA0MzIwNSwiaWF0IjoxNTg5OTUzMjA1LCJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo0NDQzIiwic3ViIjoiYXBvbXV4In0.dIsnGMSEy961FqXgJH-TBVw8_9VrzH_j4xcQJG4JY0--ekwNuMpLr0CyOJFj_XFuVsY-ZS8Lwj5yJCYHv7TS8Q`, + }, + "", + nil, + nil, + true, + }, + + { + "valid token with namespace, identities and networks restrictions", + args{ + `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsbSI6IlZpbmNlIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1ZTFjZjNlZmEzNzAwMzhmYWY3Zjg3NzciLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIiwic3ViamVjdCI6ImFwb211eCJ9LCJyZXN0cmljdGlvbnMiOnsicGVybXMiOlsiQGF1dGg6cm9sZT10ZXN0Il0sIm5hbWVzcGFjZSI6Ii9hcG9tdXgvY2hpbGQiLCJuZXR3b3JrcyI6WyIxMjcuMC4wLjEvMzIiXX0sImV4cCI6MTU5MDA0Mjk5OCwiaWF0IjoxNTg5OTUyOTk4LCJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo0NDQzIiwic3ViIjoiYXBvbXV4In0.JQcljRWeraT2Ma2u9DpeO0ub0SLNj5jDjKMVppibsm17YH6CyNKO5pyf-Kg6SldxuJau1nf0W_V7K3sQFmqj0g`, + }, + "/apomux/child", + []string{"@auth:role=test"}, + []string{"127.0.0.1/32"}, + false, + }, + { + "invalid token", + args{ + `eyJhbGciOiJFUzI1NiIsInWFsbSI6IlNlIiwicXVvdGEiOiIzIiwiZGF0YSI6eyJhY2NvdW50IjoiYXBvbXV4IiwiZW1haWwiOiJhZG1pbkBhcG9tdXguY29tIiwiaWQiOiI1YjQ5MGVjYzdkZGYxZjc1YWI4NGU3YjEiLCJvcmdhbml6YXRpb24iOiJhcG9tdXgiLCJyZWFsbSI6InZpbmNlIn0sImF1ZCI6ImFwb3JldG8uY29tIiwiZXhwIjoxNTQ3NjgzMjE4LCJpYXQiOjE1NDc1OTMyMTgsImlzcyI6Im1pZGdhcmQuYXBvbXV4LmNvbSIsInN1YiI6ImFwb211eCJ9.N7B-X3rRcySodn0q4u1NUAVFIEtjnZEYJGidAFSwflyAhpqchRmm6P_waaVBcGhnRNhsIUayuJjeMpXccYFrWA`, + }, + "", + nil, + nil, + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotNs, gotPerms, gotNetworks, err := ExtractRestrictions(tt.args.token) + if (err != nil) != tt.wantErr { + t.Errorf("ExtractRestrictions() error = %v, wantErr %v", err, tt.wantErr) + return + } + if gotNs != tt.wantNs { + t.Errorf("ExtractRestrictions() gotAuthorizedNS = %v, want %v", gotNs, tt.wantNs) + } + if !reflect.DeepEqual(gotPerms, tt.wantPerms) { + t.Errorf("ExtractRestrictions() gotAuthorizedPerms = %v, want %v", gotPerms, tt.wantPerms) + } + if !reflect.DeepEqual(gotNetworks, tt.wantNets) { + t.Errorf("ExtractRestrictions() gotNetworks = %v, want %v", gotNetworks, tt.wantNets) + } + }) + } +}