[#1689] ape: Ignore verification checks for impersonated bearer tokens
All checks were successful
Vulncheck / Vulncheck (push) Successful in 1m16s
Pre-commit hooks / Pre-commit (push) Successful in 1m40s
Build / Build Components (push) Successful in 1m49s
Tests and linters / Run gofumpt (push) Successful in 2m40s
Tests and linters / Tests (push) Successful in 3m3s
Tests and linters / Lint (push) Successful in 3m6s
Tests and linters / Staticcheck (push) Successful in 3m2s
Tests and linters / Tests with -race (push) Successful in 3m48s
Tests and linters / gopls check (push) Successful in 4m6s
OCI image / Build container images (push) Successful in 4m36s

* If token is impersonated, then only epoch checks should be performed.
  Verification checks are unnecessary: 1. An impersonated token's issuer
  can differ from container owner. 2. Request signature is defined in
  different way if token is impersonated;
* Add unit-test cases for impersonated tokens.

Change-Id: I5c89fa27a17a9467c5d61dcb8318699567fbf635
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
Airat Arifullin 2025-05-12 16:09:01 +03:00
parent bf638cce67
commit 701c2aba08
2 changed files with 33 additions and 3 deletions

View file

@ -148,6 +148,11 @@ func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKe
}
}
// Ignore verification checks if token is impersonated.
if token.Impersonate() {
return nil
}
// Then check if container owner signed this token.
if !bearer.ResolveIssuer(*token).Equals(ownerCnr) {
return errBearerNotSignedByOwner

View file

@ -297,7 +297,7 @@ func TestMessageSign(t *testing.T) {
require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet))
})
t.Run("impersonate but invalid signer", func(t *testing.T) {
t.Run("impersonate but different signer", func(t *testing.T) {
var bt bearer.Token
bt.SetExp(10)
bt.SetImpersonate(true)
@ -312,8 +312,33 @@ func TestMessageSign(t *testing.T) {
req.Body.BearerToken = bt.Marshal()
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut))
require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet))
require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet))
})
t.Run("impersonate but different issuer", func(t *testing.T) {
var bt bearer.Token
bt.SetExp(10)
bt.SetImpersonate(true)
differentUserPrivKey, err := keys.NewPrivateKey()
require.NoError(t, err)
var reqSigner user.ID
user.IDFromKey(&reqSigner, (ecdsa.PublicKey)(*differentUserPrivKey.PublicKey()))
bt.ForUser(reqSigner)
bt.SetAPEOverride(bearer.APEOverride{
Target: ape.ChainTarget{
TargetType: ape.TargetTypeContainer,
Name: cid1.EncodeToString(),
},
Chains: []ape.Chain{},
})
require.NoError(t, bt.Sign(privs[0].PrivateKey))
req.Body.BearerToken = bt.Marshal()
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet))
})
bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey())