poc impersonate #39

Merged
KirillovDenis merged 1 commit from KirillovDenis/poc/impersonate into master 2023-05-04 06:42:25 +00:00
6 changed files with 39 additions and 11 deletions
Showing only changes of commit b366e75366 - Show all commits

View file

@ -20,6 +20,7 @@ This document outlines major changes between releases.
- Support string `Action` and `Resource` fields in `bucketPolicy.Statement` (TrueCloudLab#32)
- Add new `kludge.use_default_xmlns_for_complete_multipart` config param (TrueCloudLab#40)
- Support dump metrics descriptions (#80)
- Support impersonate bearer token (#81)
### Changed
- Update syncTree.sh due to recent renaming (#73)

View file

@ -329,7 +329,7 @@ func (n *layer) Owner(ctx context.Context) user.ID {
func (n *layer) prepareAuthParameters(ctx context.Context, prm *PrmAuth, bktOwner user.ID) {
if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil && bd.Gate.BearerToken != nil {
if bktOwner.Equals(bearer.ResolveIssuer(*bd.Gate.BearerToken)) {
if bd.Gate.BearerToken.Impersonate() || bktOwner.Equals(bearer.ResolveIssuer(*bd.Gate.BearerToken)) {
prm.BearerToken = bd.Gate.BearerToken
return
}

View file

@ -99,6 +99,7 @@ type (
FrostFSKey *keys.PrivateKey
GatesPublicKeys []*keys.PublicKey
EACLRules []byte
Impersonate bool
SessionTokenRules []byte
SkipSessionRules bool
Lifetime time.Duration
@ -344,16 +345,21 @@ func restrictedRecords() (records []*eacl.Record) {
return
}
func buildBearerToken(key *keys.PrivateKey, table *eacl.Table, lifetime lifetimeOptions, gateKey *keys.PublicKey) (*bearer.Token, error) {
func buildBearerToken(key *keys.PrivateKey, impersonate bool, table *eacl.Table, lifetime lifetimeOptions, gateKey *keys.PublicKey) (*bearer.Token, error) {
var ownerID user.ID
user.IDFromKey(&ownerID, (ecdsa.PublicKey)(*gateKey))
var bearerToken bearer.Token
bearerToken.SetEACLTable(*table)
if !impersonate {
bearerToken.SetEACLTable(*table)
}
bearerToken.ForUser(ownerID)
bearerToken.SetExp(lifetime.Exp)
bearerToken.SetIat(lifetime.Iat)
bearerToken.SetNbf(lifetime.Iat)
bearerToken.SetImpersonate(impersonate)
err := bearerToken.Sign(key.PrivateKey)
if err != nil {
@ -363,10 +369,10 @@ func buildBearerToken(key *keys.PrivateKey, table *eacl.Table, lifetime lifetime
return &bearerToken, nil
}
func buildBearerTokens(key *keys.PrivateKey, table *eacl.Table, lifetime lifetimeOptions, gatesKeys []*keys.PublicKey) ([]*bearer.Token, error) {
func buildBearerTokens(key *keys.PrivateKey, impersonate bool, table *eacl.Table, lifetime lifetimeOptions, gatesKeys []*keys.PublicKey) ([]*bearer.Token, error) {
bearerTokens := make([]*bearer.Token, 0, len(gatesKeys))
for _, gateKey := range gatesKeys {
tkn, err := buildBearerToken(key, table, lifetime, gateKey)
tkn, err := buildBearerToken(key, impersonate, table, lifetime, gateKey)
if err != nil {
return nil, fmt.Errorf("build bearer token: %w", err)
}
@ -413,7 +419,8 @@ func createTokens(options *IssueSecretOptions, lifetime lifetimeOptions) ([]*acc
if err != nil {
return nil, fmt.Errorf("failed to build eacl table: %w", err)
}
bearerTokens, err := buildBearerTokens(options.FrostFSKey, table, lifetime, options.GatesPublicKeys)
bearerTokens, err := buildBearerTokens(options.FrostFSKey, options.Impersonate, table, lifetime, options.GatesPublicKeys)
if err != nil {
return nil, fmt.Errorf("failed to build bearer tokens: %w", err)
}

View file

@ -56,6 +56,7 @@ var (
accountAddressFlag string
peerAddressFlag string
eaclRulesFlag string
disableImpersonateFlag bool
gateWalletPathFlag string
gateAccountAddressFlag string
accessKeyIDFlag string
@ -207,10 +208,16 @@ func issueSecret() *cli.Command {
},
&cli.StringFlag{
Name: "bearer-rules",
Usage: "rules for bearer token (filepath or a plain json string are allowed)",
Usage: "rules for bearer token (filepath or a plain json string are allowed, can be used only with --disable-impersonate)",
Required: false,
Destination: &eaclRulesFlag,
},
&cli.BoolFlag{
Name: "disable-impersonate",
Usage: "mark token as not impersonate to don't consider token signer as request owner (must be provided to use --bearer-rules flag)",
Required: false,
Destination: &disableImpersonateFlag,
},
&cli.StringSliceFlag{
Name: "gate-public-key",
Usage: "public 256r1 key of a gate (use flags repeatedly for multiple gates)",
@ -345,6 +352,10 @@ It will be ceil rounded to the nearest amount of epoch.`,
return cli.Exit(fmt.Sprintf("couldn't parse container policy: %s", err.Error()), 6)
}
if !disableImpersonateFlag && eaclRulesFlag != "" {
return cli.Exit("--bearer-rules flag can be used only with --disable-impersonate", 6)
}
bearerRules, err := getJSONRules(eaclRulesFlag)
if err != nil {
return cli.Exit(fmt.Sprintf("couldn't parse 'bearer-rules' flag: %s", err.Error()), 7)
@ -364,6 +375,7 @@ It will be ceil rounded to the nearest amount of epoch.`,
FrostFSKey: key,
GatesPublicKeys: gatesPublicKeys,
EACLRules: bearerRules,
Impersonate: !disableImpersonateFlag,
SessionTokenRules: sessionRules,
SkipSessionRules: skipSessionRules,
ContainerPolicies: policies,

View file

@ -139,12 +139,19 @@ the secret. Format of `access_key_id`: `%cid0%oid`, where 0(zero) is a delimiter
Creation of bearer tokens is mandatory.
Rules for a bearer token can be set via parameter `--bearer-rules` (json-string and file path allowed):
By default, bearer token will be created with `impersonate` flag and won't have eACL table. It means that gate which will use such token
to interact with node can have access to your private containers or to containers in which eACL grants access to you
by public key.
Rules for a bearer token can be set via parameter `--bearer-rules` (json-string and file path allowed).
But you must provide `--disable-impersonate` flag:
```shell
$ frostfs-s3-authmate issue-secret --wallet wallet.json \
--peer 192.168.130.71:8080 \
--gate-public-key 0313b1ac3a8076e155a7e797b24f0b650cccad5941ea59d7cfd51a024a8b2a06bf \
--bearer-rules bearer-rules.json
--bearer-rules bearer-rules.json \
--disable-impersonate
```
where content of `bearer-rules.json`:
```json

View file

@ -8,12 +8,13 @@ import (
"strings"
"sync/atomic"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
grpcService "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/services/tree"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/service/tree"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"go.uber.org/zap"
"google.golang.org/grpc"
@ -385,7 +386,7 @@ func metaToKV(meta map[string]string) []*grpcService.KeyValue {
func getBearer(ctx context.Context, bktInfo *data.BucketInfo) []byte {
if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil {
if bd.Gate.BearerToken != nil {
if bktInfo.Owner.Equals(bearer.ResolveIssuer(*bd.Gate.BearerToken)) {
if bd.Gate.BearerToken.Impersonate() || bktInfo.Owner.Equals(bearer.ResolveIssuer(*bd.Gate.BearerToken)) {
return bd.Gate.BearerToken.Marshal()
}
}