Skip to content

Commit 1ab4b9e

Browse files
AuthZ: Implementation, tests and docs (#193)
* AuthZ: Implementation, tests and docs * add example and beta tags in docs
1 parent 3b420d8 commit 1ab4b9e

File tree

9 files changed

+879
-0
lines changed

9 files changed

+879
-0
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- AuthZ service support
13+
14+
1015
## v3.8.0-beta.2 - 2024-03-20
1116

1217
### Added

examples/.examples-ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ go-sdk-examples:
1313
- vault
1414
- share
1515
- sanitize
16+
- authz
1617
image: golang:${GO_VERSION}
1718
before_script:
1819
- export PANGEA_AUDIT_CONFIG_ID="${PANGEA_AUDIT_CONFIG_ID_1_LVE_AWS}"
@@ -35,6 +36,7 @@ go-sdk-examples:
3536
- export PANGEA_VAULT_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}"
3637
- export PANGEA_SHARE_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}"
3738
- export PANGEA_SANITIZE_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}"
39+
- export PANGEA_AUTHZ_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}"
3840
script:
3941
- cd examples/${EXAMPLE_FOLDER}
4042
- bash ../../dev/run_examples.sh

examples/authz/authz_cycle.go

+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"os"
8+
"time"
9+
10+
"github.com/pangeacyber/pangea-go/pangea-sdk/v3/pangea"
11+
"github.com/pangeacyber/pangea-go/pangea-sdk/v3/service/authz"
12+
)
13+
14+
const (
15+
namespaceFolder = "folder"
16+
namespaceUser = "user"
17+
relationOwner = "owner"
18+
relationEditor = "editor"
19+
relationReader = "reader"
20+
)
21+
22+
func main() {
23+
var timeNow = time.Now()
24+
var timeStr = timeNow.Format("20060102_150405")
25+
var folder1 = "folder_1_" + timeStr
26+
var folder2 = "folder_2_" + timeStr
27+
var user1 = "user_1_" + timeStr
28+
var user2 = "user_2_" + timeStr
29+
30+
// Load Pangea token from environment variables
31+
token := os.Getenv("PANGEA_AUTHZ_TOKEN")
32+
if token == "" {
33+
log.Fatal("Unauthorized: No token present.")
34+
}
35+
36+
ctx, cancelFn := context.WithTimeout(context.Background(), 120*time.Second)
37+
defer cancelFn()
38+
39+
// create a new AuthZ client with pangea token and domain
40+
client := authz.New(&pangea.Config{
41+
Token: token,
42+
Domain: os.Getenv("PANGEA_DOMAIN"),
43+
QueuedRetryEnabled: true,
44+
PollResultTimeout: 120 * time.Second,
45+
Retry: true,
46+
RetryConfig: &pangea.RetryConfig{
47+
RetryMax: 4,
48+
},
49+
})
50+
51+
// Create tuples
52+
fmt.Println("Creating tuples...")
53+
_, err := client.TupleCreate(ctx, &authz.TupleCreateRequest{
54+
Tuples: []authz.Tuple{
55+
authz.Tuple{
56+
Resource: authz.Resource{
57+
Namespace: namespaceFolder,
58+
ID: folder1,
59+
},
60+
Relation: relationReader,
61+
Subject: authz.Subject{
62+
Namespace: namespaceUser,
63+
ID: user1,
64+
},
65+
},
66+
authz.Tuple{
67+
Resource: authz.Resource{
68+
Namespace: namespaceFolder,
69+
ID: folder1,
70+
},
71+
Relation: relationEditor,
72+
Subject: authz.Subject{
73+
Namespace: namespaceUser,
74+
ID: user2,
75+
},
76+
},
77+
authz.Tuple{
78+
Resource: authz.Resource{
79+
Namespace: namespaceFolder,
80+
ID: folder2,
81+
},
82+
Relation: relationEditor,
83+
Subject: authz.Subject{
84+
Namespace: namespaceUser,
85+
ID: user1,
86+
},
87+
},
88+
authz.Tuple{
89+
Resource: authz.Resource{
90+
Namespace: namespaceFolder,
91+
ID: folder2,
92+
},
93+
Relation: relationOwner,
94+
Subject: authz.Subject{
95+
Namespace: namespaceUser,
96+
ID: user2,
97+
},
98+
},
99+
},
100+
})
101+
if err != nil {
102+
log.Fatalf("Unexpected error.", err)
103+
}
104+
fmt.Println("Tuples created.")
105+
106+
// Tuple list with resource
107+
fmt.Println("Listing tuples with resource...")
108+
filter := authz.NewFilterUserList()
109+
filter.ResourceNamespace().Set(pangea.String(namespaceFolder))
110+
filter.ResourceID().Set(pangea.String(folder1))
111+
112+
rListWithResource, err := client.TupleList(ctx, &authz.TupleListRequest{
113+
Filter: filter.Filter(),
114+
})
115+
if err != nil {
116+
log.Fatalf("Unexpected error.", err)
117+
}
118+
119+
fmt.Printf("Got %d tuples.\n", rListWithResource.Result.Count)
120+
for i, tuple := range rListWithResource.Result.Tuples {
121+
fmt.Printf("Tuple #%d\n", i)
122+
fmt.Printf("\tNamespace: %s\n", tuple.Subject.Namespace)
123+
fmt.Printf("\tID: %s\n", tuple.Subject.ID)
124+
}
125+
126+
// Tuple list with subject
127+
filter = authz.NewFilterUserList()
128+
fmt.Println("Listing tuples with subject...")
129+
filter.SubjectNamespace().Set(pangea.String(namespaceUser))
130+
filter.SubjectID().Set(pangea.String(user1))
131+
132+
rListWithSubject, err := client.TupleList(ctx, &authz.TupleListRequest{
133+
Filter: filter.Filter(),
134+
})
135+
if err != nil {
136+
log.Fatalf("Unexpected error.", err)
137+
}
138+
139+
fmt.Printf("Got %d tuples.\n", rListWithSubject.Result.Count)
140+
for i, tuple := range rListWithResource.Result.Tuples {
141+
fmt.Printf("Tuple #%d\n", i)
142+
fmt.Printf("\tNamespace: %s\n", tuple.Subject.Namespace)
143+
fmt.Printf("\tID: %s\n", tuple.Subject.ID)
144+
}
145+
146+
// Tuple delete
147+
fmt.Println("Deleting tuples...")
148+
_, err = client.TupleDelete(ctx, &authz.TupleDeleteRequest{
149+
Tuples: []authz.Tuple{
150+
authz.Tuple{
151+
Resource: authz.Resource{
152+
Namespace: namespaceFolder,
153+
ID: folder1,
154+
},
155+
Relation: relationReader,
156+
Subject: authz.Subject{
157+
Namespace: namespaceUser,
158+
ID: user1,
159+
},
160+
},
161+
},
162+
})
163+
if err != nil {
164+
log.Fatalf("Unexpected error.", err)
165+
}
166+
fmt.Println("Delete success.")
167+
168+
// Check no debug
169+
fmt.Println("Checking tuple...")
170+
rCheck, err := client.Check(ctx, &authz.CheckRequest{
171+
Resource: authz.Resource{
172+
Namespace: namespaceFolder,
173+
ID: folder1,
174+
},
175+
Action: "reader",
176+
Subject: authz.Subject{
177+
Namespace: namespaceUser,
178+
ID: user2,
179+
},
180+
})
181+
if err != nil {
182+
log.Fatalf("Unexpected error.", err)
183+
}
184+
185+
if rCheck.Result.Allowed {
186+
fmt.Println("Subject IS allowed to read resource")
187+
} else {
188+
fmt.Println("Subject is NOT allowed to read resource")
189+
}
190+
191+
// Check debug
192+
fmt.Println("Checking tuple with debug enabled...")
193+
rCheck, err = client.Check(ctx, &authz.CheckRequest{
194+
Resource: authz.Resource{
195+
Namespace: namespaceFolder,
196+
ID: folder1,
197+
},
198+
Action: "editor",
199+
Subject: authz.Subject{
200+
Namespace: namespaceUser,
201+
ID: user2,
202+
},
203+
Debug: pangea.Bool(true),
204+
})
205+
if err != nil {
206+
log.Fatalf("Unexpected error.", err)
207+
}
208+
209+
if rCheck.Result.Allowed {
210+
fmt.Println("Subject IS allowed to edit resource")
211+
} else {
212+
fmt.Println("Subject is NOT allowed to edit resource")
213+
}
214+
if rCheck.Result.Debug != nil {
215+
fmt.Printf("Debug data: %s\n", pangea.Stringify(*rCheck.Result.Debug))
216+
}
217+
218+
// List resources
219+
fmt.Println("Listing resources...")
220+
rListResources, err := client.ListResources(ctx, &authz.ListResourcesRequest{
221+
Namespace: namespaceFolder,
222+
Action: relationEditor,
223+
Subject: authz.Subject{
224+
Namespace: namespaceUser,
225+
ID: user2,
226+
},
227+
})
228+
if err != nil {
229+
log.Fatalf("Unexpected error.", err)
230+
}
231+
232+
fmt.Printf("Got %d resources.\n", len(rListResources.Result.IDs))
233+
for i, id := range rListResources.Result.IDs {
234+
fmt.Printf("Resource #%d. ID: %s\n", i, id)
235+
}
236+
237+
// List subjects
238+
fmt.Println("Listing subjects...")
239+
rListSubjects, err := client.ListSubjects(ctx, &authz.ListSubjectsRequest{
240+
Resource: authz.Resource{
241+
Namespace: namespaceFolder,
242+
ID: folder2,
243+
},
244+
Action: relationEditor,
245+
})
246+
if err != nil {
247+
log.Fatalf("Unexpected error.", err)
248+
}
249+
250+
fmt.Printf("Got %d subjects.\n", len(rListSubjects.Result.Subjects))
251+
for i, subject := range rListSubjects.Result.Subjects {
252+
fmt.Printf("Tuple #%d\n", i)
253+
fmt.Printf("\tNamespace: %s\n", subject.Namespace)
254+
fmt.Printf("\tID: %s\n", subject.ID)
255+
}
256+
257+
}

examples/authz/go.mod

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module examples/share
2+
3+
go 1.19
4+
5+
require github.com/pangeacyber/pangea-go/pangea-sdk/v3 v3.8.0
6+
7+
require (
8+
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
9+
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
10+
github.com/mattn/go-colorable v0.1.13 // indirect
11+
github.com/mattn/go-isatty v0.0.20 // indirect
12+
github.com/rs/zerolog v1.31.0 // indirect
13+
golang.org/x/sys v0.15.0 // indirect
14+
)
15+
16+
replace github.com/pangeacyber/pangea-go/pangea-sdk/v3 v3.8.0 => ../../pangea-sdk/v3

examples/authz/go.sum

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
2+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
5+
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
6+
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
7+
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
8+
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
9+
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
10+
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
11+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
12+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
13+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
14+
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
15+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
16+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
17+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
18+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
19+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
20+
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
21+
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
22+
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
23+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
24+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
25+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
26+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
27+
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
28+
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
29+
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
30+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

pangea-sdk/.sdk-ci.yml

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ sdk-test-it:
2121
SERVICE_VAULT_ENV: LVE
2222
SERVICE_SHARE_ENV: LVE
2323
SERVICE_SANITIZE_ENV: LVE
24+
SERVICE_AUTHZ_ENV: DEV
2425
before_script:
2526
- echo $ENV
2627
- echo $CLOUD
@@ -81,6 +82,9 @@ sdk-test-it:
8182
- CLOUD: [AWS] # FIXME: Add GCP when supported
8283
ENV: ${SERVICE_SANITIZE_ENV}
8384
TEST: sanitize
85+
- CLOUD: [AWS, GCP]
86+
ENV: ${SERVICE_AUTHZ_ENV}
87+
TEST: authz
8488
rules:
8589
- if: $CI_COMMIT_BRANCH
8690
script:

0 commit comments

Comments
 (0)