.forgejo: add build/test workflows #478
4 changed files with 147 additions and 41 deletions
38
.forgejo/workflows/build.yml
Normal file
38
.forgejo/workflows/build.yml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
name: Build
|
||||||
|
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build Components
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go_versions: [ '1.19', '1.20' ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
# Allows to fetch all history for all branches and tags.
|
||||||
|
# Need this for proper versioning.
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '${{ matrix.go_versions }}'
|
||||||
|
|
||||||
|
- name: Build CLI
|
||||||
|
run: make bin/frostfs-cli
|
||||||
|
|
||||||
|
- name: Build NODE
|
||||||
|
run: make bin/frostfs-node
|
||||||
|
|
||||||
|
- name: Build IR
|
||||||
|
run: make bin/frostfs-ir
|
||||||
|
|
||||||
|
- name: Build ADM
|
||||||
|
run: make bin/frostfs-adm
|
||||||
|
|
||||||
|
- name: Build LENS
|
||||||
|
run: make bin/frostfs-lens
|
54
.forgejo/workflows/tests.yml
Normal file
54
.forgejo/workflows/tests.yml
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
name: Tests and linters
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: Lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '1.20'
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: https://github.com/golangci/golangci-lint-action@v3
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
tests:
|
||||||
|
name: Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go_versions: [ '1.19', '1.20' ]
|
||||||
|
fail-fast: false
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '${{ matrix.go_versions }}'
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: make test
|
||||||
|
|
||||||
|
tests-race:
|
||||||
|
name: Tests with -race
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '1.20'
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: go test ./... -count=1 -race
|
|
@ -4,7 +4,7 @@
|
||||||
# options for analysis running
|
# options for analysis running
|
||||||
run:
|
run:
|
||||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||||
timeout: 10m
|
timeout: 20m
|
||||||
|
|
||||||
# include test files or not, default is true
|
# include test files or not, default is true
|
||||||
tests: false
|
tests: false
|
||||||
|
|
|
@ -51,20 +51,10 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if op == acl.OpObjectGet {
|
|
||||||
// verify if the request for a client operation
|
isAuthorized, err := s.isAuthorized(req, op)
|
||||||
// was signed by a key from authorized list.
|
if isAuthorized || err != nil {
|
||||||
// Operation must be one of READ.
|
return err
|
||||||
sign := req.GetSignature()
|
|
||||||
if sign == nil {
|
|
||||||
return errors.New("missing signature")
|
|
||||||
}
|
|
||||||
var key = sign.GetKey()
|
|
||||||
for i := range s.authorizedKeys {
|
|
||||||
if bytes.Equal(s.authorizedKeys[i], key) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cnr, err := s.cnrSource.Get(cid)
|
cnr, err := s.cnrSource.Get(cid)
|
||||||
|
@ -74,18 +64,9 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op
|
||||||
|
|
||||||
eaclOp := eACLOp(op)
|
eaclOp := eACLOp(op)
|
||||||
|
|
||||||
var bt *bearer.Token
|
bt, err := parseBearer(rawBearer, cid, eaclOp)
|
||||||
if len(rawBearer) > 0 {
|
if err != nil {
|
||||||
bt = new(bearer.Token)
|
return err
|
||||||
if err = bt.Unmarshal(rawBearer); err != nil {
|
|
||||||
return eACLErr(eaclOp, fmt.Errorf("invalid bearer token: %w", err))
|
|
||||||
}
|
|
||||||
if !bt.AssertContainer(cid) {
|
|
||||||
return eACLErr(eaclOp, errBearerWrongContainer)
|
|
||||||
}
|
|
||||||
if !bt.VerifySignature() {
|
|
||||||
return eACLErr(eaclOp, errBearerSignature)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
role, err := roleFromReq(cnr, req, bt)
|
role, err := roleFromReq(cnr, req, bt)
|
||||||
|
@ -117,32 +98,65 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op
|
||||||
|
|
||||||
var tb eacl.Table
|
var tb eacl.Table
|
||||||
signer := req.GetSignature().GetKey()
|
signer := req.GetSignature().GetKey()
|
||||||
if tableFromBearer {
|
if tableFromBearer && !bt.Impersonate() {
|
||||||
if bt.Impersonate() {
|
|
||||||
tbCore, err := s.eaclSource.GetEACL(cid)
|
|
||||||
if err != nil {
|
|
||||||
return handleGetEACLError(err)
|
|
||||||
}
|
|
||||||
tb = *tbCore.Value
|
|
||||||
signer = bt.SigningKeyBytes()
|
|
||||||
} else {
|
|
||||||
if !bearer.ResolveIssuer(*bt).Equals(cnr.Value.Owner()) {
|
if !bearer.ResolveIssuer(*bt).Equals(cnr.Value.Owner()) {
|
||||||
return eACLErr(eaclOp, errBearerWrongOwner)
|
return eACLErr(eaclOp, errBearerWrongOwner)
|
||||||
}
|
}
|
||||||
tb = bt.EACLTable()
|
tb = bt.EACLTable()
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
tbCore, err := s.eaclSource.GetEACL(cid)
|
tbCore, err := s.eaclSource.GetEACL(cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleGetEACLError(err)
|
return handleGetEACLError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tb = *tbCore.Value
|
tb = *tbCore.Value
|
||||||
|
|
||||||
|
if bt.Impersonate() {
|
||||||
|
signer = bt.SigningKeyBytes()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkEACL(tb, signer, eACLRole(role), eaclOp)
|
return checkEACL(tb, signer, eACLRole(role), eaclOp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true iff the operation is read-only and request was signed
|
||||||
|
// with one of the authorized keys.
|
||||||
|
func (s *Service) isAuthorized(req message, op acl.Op) (bool, error) {
|
||||||
|
if op != acl.OpObjectGet {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sign := req.GetSignature()
|
||||||
|
if sign == nil {
|
||||||
|
return false, errors.New("missing signature")
|
||||||
|
}
|
||||||
|
|
||||||
|
key := sign.GetKey()
|
||||||
|
for i := range s.authorizedKeys {
|
||||||
|
if bytes.Equal(s.authorizedKeys[i], key) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBearer(rawBearer []byte, cid cidSDK.ID, eaclOp eacl.Operation) (*bearer.Token, error) {
|
||||||
|
if len(rawBearer) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bt := new(bearer.Token)
|
||||||
|
if err := bt.Unmarshal(rawBearer); err != nil {
|
||||||
|
return nil, eACLErr(eaclOp, fmt.Errorf("invalid bearer token: %w", err))
|
||||||
|
}
|
||||||
|
if !bt.AssertContainer(cid) {
|
||||||
|
return nil, eACLErr(eaclOp, errBearerWrongContainer)
|
||||||
|
}
|
||||||
|
if !bt.VerifySignature() {
|
||||||
|
return nil, eACLErr(eaclOp, errBearerSignature)
|
||||||
|
}
|
||||||
|
return bt, nil
|
||||||
|
}
|
||||||
|
|
||||||
func handleGetEACLError(err error) error {
|
func handleGetEACLError(err error) error {
|
||||||
if client.IsErrEACLNotFound(err) {
|
if client.IsErrEACLNotFound(err) {
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in a new issue