Skip to content

Commit 4b4686a

Browse files
committed
1 parent f81cd44 commit 4b4686a

File tree

10 files changed

+336
-0
lines changed

10 files changed

+336
-0
lines changed

.github/workflows/static_check.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Merge check
2+
on: [push, pull_request]
3+
jobs:
4+
build:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- name: Set up Go 1.16
8+
uses: actions/setup-go@v1
9+
with:
10+
go-version: 1.16
11+
id: go
12+
- name: Check out code into the Go module directory
13+
uses: actions/checkout@v1
14+
- name: UT
15+
run: |
16+
go test ./...

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@
1313

1414
# Dependency directories (remove the comment below to include it)
1515
# vendor/
16+
.idea

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/go-chassis/cari
33
go 1.13
44

55
require (
6+
github.com/deckarep/golang-set v1.7.1
67
github.com/gogo/protobuf v1.3.1
78
github.com/stretchr/testify v1.6.1
89
)

go.sum

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
4+
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
5+
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
6+
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
7+
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
8+
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
9+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
11+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
12+
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
13+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
14+
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
15+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
16+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
17+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
18+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

rbac/api.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
// Package rbac extract common functions to help component to implement a auth system
19+
package rbac
20+
21+
import (
22+
"context"
23+
mapset "github.com/deckarep/golang-set"
24+
)
25+
26+
const (
27+
ClaimsUser = "account"
28+
ClaimsRoles = "roles"
29+
)
30+
31+
var whiteAPIList = mapset.NewSet()
32+
33+
func AccountFromContext(ctx context.Context) (*Account, error) {
34+
m, err := FromContext(ctx)
35+
if err != nil {
36+
return nil, err
37+
}
38+
accountNameI := m[ClaimsUser]
39+
a, ok := accountNameI.(string)
40+
if !ok {
41+
return nil, ErrConvert
42+
}
43+
roles := m[ClaimsRoles]
44+
roleList, err := GetRolesList(roles)
45+
if err != nil {
46+
return nil, ErrConvert
47+
}
48+
account := &Account{Name: a, Roles: roleList}
49+
return account, nil
50+
}
51+
52+
// RoleFromContext only return role name
53+
func RoleFromContext(ctx context.Context) (string, error) {
54+
m, err := FromContext(ctx)
55+
if err != nil {
56+
return "", err
57+
}
58+
roleI := m[ClaimsRoles]
59+
role, ok := roleI.(string)
60+
if !ok {
61+
return "", ErrConvert
62+
}
63+
return role, nil
64+
}
65+
66+
// GetRolesList return role list string
67+
func GetRolesList(v interface{}) ([]string, error) {
68+
s, ok := v.([]interface{})
69+
if !ok {
70+
return nil, ErrConvert
71+
}
72+
rolesList := make([]string, 0)
73+
for _, v := range s {
74+
role, ok := v.(string)
75+
if !ok {
76+
return nil, ErrConvert
77+
}
78+
rolesList = append(rolesList, role)
79+
}
80+
return rolesList, nil
81+
}
82+
83+
func Add2WhiteAPIList(path ...string) {
84+
for _, p := range path {
85+
whiteAPIList.Add(p)
86+
}
87+
}
88+
func MustAuth(pattern string) bool {
89+
return !whiteAPIList.Contains(pattern)
90+
}

rbac/api_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package rbac_test
19+
20+
import (
21+
"context"
22+
"github.com/go-chassis/cari/rbac"
23+
"testing"
24+
25+
"github.com/stretchr/testify/assert"
26+
)
27+
28+
func TestFromContext(t *testing.T) {
29+
ctx := rbac.NewContext(context.TODO(), map[string]interface{}{
30+
rbac.ClaimsUser: "root",
31+
rbac.ClaimsRoles: []interface{}{},
32+
})
33+
34+
claims, _ := rbac.FromContext(ctx)
35+
u := claims[rbac.ClaimsUser]
36+
r := claims[rbac.ClaimsRoles]
37+
assert.Equal(t, "root", u)
38+
assert.Equal(t, []interface{}{}, r)
39+
40+
a, err := rbac.AccountFromContext(ctx)
41+
assert.NoError(t, err)
42+
assert.Equal(t, "root", a.Name)
43+
assert.Equal(t, []string{}, a.Roles)
44+
}
45+
46+
func TestMustAuth(t *testing.T) {
47+
rbac.Add2WhiteAPIList("/test")
48+
rbac.Add2WhiteAPIList("/test1")
49+
assert.False(t, rbac.MustAuth("/test"))
50+
assert.False(t, rbac.MustAuth("/test1"))
51+
assert.True(t, rbac.MustAuth("/auth"))
52+
assert.True(t, rbac.MustAuth("/version"))
53+
assert.True(t, rbac.MustAuth("/v4/a/registry/version"))
54+
assert.True(t, rbac.MustAuth("/health"))
55+
assert.True(t, rbac.MustAuth("/v4/a/registry/health"))
56+
}

rbac/context.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package rbac
19+
20+
import (
21+
"context"
22+
)
23+
24+
// key is an unexported type for keys defined in this package.
25+
// This prevents collisions with keys defined in other packages.
26+
type key string
27+
28+
// accountKey is the key for claim values in Contexts. It is
29+
// unexported; clients use NewContext and FromContext
30+
// instead of using this key directly.
31+
var accountKey key
32+
33+
// NewContext returns a new Context that carries value claims.
34+
// claims include roles and account name
35+
func NewContext(ctx context.Context, claims map[string]interface{}) context.Context {
36+
return context.WithValue(ctx, accountKey, claims)
37+
}
38+
39+
// FromContext returns the account claims stored in ctx.
40+
func FromContext(ctx context.Context) (map[string]interface{}, error) {
41+
claims := ctx.Value(accountKey)
42+
m, ok := claims.(map[string]interface{})
43+
if !ok {
44+
return nil, ErrInvalidCtx
45+
}
46+
return m, nil
47+
}

rbac/error.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package rbac
19+
20+
import (
21+
"errors"
22+
)
23+
24+
var (
25+
ErrInvalidHeader = errors.New("invalid auth header")
26+
ErrNoHeader = errors.New("should provide Authorization header")
27+
ErrInvalidCtx = errors.New("invalid context")
28+
ErrConvert = errors.New("type convert error")
29+
)

rbac/resource_map.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package rbac
19+
20+
//as a user, he only understand resource of this system,
21+
//but to decouple authorization code from business code,
22+
//a middleware should handle all the authorization logic, and this middleware only understand rest API,
23+
//a resource mapping helps to maintain relations between api and resource.
24+
var resourceMap = map[string]string{}
25+
26+
func GetResource(api string) string {
27+
r, ok := resourceMap[api]
28+
if !ok {
29+
return resourceMap["*"]
30+
}
31+
return r
32+
}
33+
34+
// MapResource save the mapping from api to resource
35+
func MapResource(api, resource string) {
36+
resourceMap[api] = resource
37+
}

rbac/resource_map_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package rbac_test
19+
20+
import (
21+
"github.com/go-chassis/cari/rbac"
22+
"github.com/stretchr/testify/assert"
23+
"testing"
24+
)
25+
26+
func TestGetResource(t *testing.T) {
27+
t.Run("given empty mapping,return empty resource", func(t *testing.T) {
28+
res := rbac.GetResource("/test")
29+
assert.Empty(t, res)
30+
})
31+
t.Run("add api and resource mapping,return resource", func(t *testing.T) {
32+
rbac.MapResource("/v1/order/1", "order")
33+
res := rbac.GetResource("/v1/order/1")
34+
assert.NotEmpty(t, res)
35+
})
36+
t.Run("add api and resource mapping,return empty resource", func(t *testing.T) {
37+
rbac.MapResource("/v1/item/1", "order")
38+
res := rbac.GetResource("/v1/a/1")
39+
assert.Empty(t, res)
40+
})
41+
}

0 commit comments

Comments
 (0)