diff --git a/auth/authenticator.go b/auth/authenticator.go index 87e0cd4..e838cfb 100644 --- a/auth/authenticator.go +++ b/auth/authenticator.go @@ -150,5 +150,6 @@ func (u *Authenticator) getBearerToken(ctx context.Context, email string) (strin return "", "", err } - return u.generator.NewBearer(email, infoRes.CurrentEpoch()) + msPerEpoch := infoRes.MsPerBlock() * int64(infoRes.EpochDuration()) + return u.generator.NewBearer(email, infoRes.CurrentEpoch(), msPerEpoch) } diff --git a/bearer/bearer.go b/bearer/bearer.go index c414d8d..0820495 100644 --- a/bearer/bearer.go +++ b/bearer/bearer.go @@ -4,11 +4,12 @@ import ( "crypto/sha256" "encoding/base64" "fmt" + "strconv" + "time" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neofs-sdk-go/bearer" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" - neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/user" @@ -26,17 +27,21 @@ func NewGenerator(config *Config) *Generator { // Config for bearer token generator. type Config struct { - EmailAttr string - Key *keys.PrivateKey - UserID *user.ID - ContainerID cid.ID - LifeTime uint64 + EmailAttr string + Key *keys.PrivateKey + UserID *user.ID + ContainerID cid.ID + LifeTime uint64 + MaxObjectSize uint64 + ObjectMaxLifetime time.Duration } // NewBearer generates new token for supplied email. -func (b *Generator) NewBearer(email string, currentEpoch uint64) (string, string, error) { +func (b *Generator) NewBearer(email string, currentEpoch uint64, msPerEpoch int64) (string, string, error) { hashedEmail := fmt.Sprintf("%x", sha256.Sum256([]byte(email))) + epochs := uint64(b.config.ObjectMaxLifetime.Milliseconds() / msPerEpoch) + t := eacl.CreateTable(b.config.ContainerID) // order of rec is important rec := eacl.CreateRecord(eacl.ActionAllow, eacl.OperationPut) @@ -47,6 +52,11 @@ func (b *Generator) NewBearer(email string, currentEpoch uint64) (string, string rec.AddFilter(eacl.HeaderFromObject, eacl.MatchStringNotEqual, object.AttributeContentType, "text/html") rec.AddFilter(eacl.HeaderFromObject, eacl.MatchStringNotEqual, object.AttributeContentType, "text/htmlh") rec.AddFilter(eacl.HeaderFromObject, eacl.MatchStringNotEqual, object.AttributeContentType, "") + rec.AddObjectPayloadLengthFilter(eacl.MatchNumLE, b.config.MaxObjectSize) + + maxExpirationEpoch := strconv.FormatUint(currentEpoch+b.config.LifeTime+epochs, 10) + rec.AddFilter(eacl.HeaderFromObject, eacl.MatchStringEqual, object.AttributeExpirationEpoch, maxExpirationEpoch) + eacl.AddFormedTarget(rec, eacl.RoleOthers) t.AddRecord(rec) rec2 := eacl.CreateRecord(eacl.ActionDeny, eacl.OperationPut) @@ -60,7 +70,7 @@ func (b *Generator) NewBearer(email string, currentEpoch uint64) (string, string } bt.SetExp(currentEpoch + b.config.LifeTime) - if err := bt.Sign(neofsecdsa.SignerRFC6979(b.config.Key.PrivateKey)); err != nil { + if err := bt.Sign(user.NewAutoIDSignerRFC6979(b.config.Key.PrivateKey)); err != nil { return "", "", err } diff --git a/cmd/neofs-oauthz/app.go b/cmd/neofs-oauthz/app.go index 3454323..f38ef6d 100644 --- a/cmd/neofs-oauthz/app.go +++ b/cmd/neofs-oauthz/app.go @@ -213,6 +213,14 @@ func (a *app) initAuthCfg(key *keys.PrivateKey) { if lifetime == 0 { lifetime = defaultBearerLifetime } + maxObjectSize := a.cfg.GetUint64(cfgBearerMaxObjectSize) + if maxObjectSize == 0 { + maxObjectSize = defaultMaxObjectSize + } + objectMaxLifetime := a.cfg.GetDuration(cfgBearerMaxObjectLifetime) + if objectMaxLifetime == 0 { + objectMaxLifetime = defaultMaxObjectLifetime + } listenAddress := a.cfg.GetString(cfgListenAddress) if len(listenAddress) == 0 { @@ -225,11 +233,13 @@ func (a *app) initAuthCfg(key *keys.PrivateKey) { a.authCfg = &auth.Config{ Bearer: &bearer.Config{ - EmailAttr: emailattr, - Key: key, - UserID: userID, - ContainerID: containerID, - LifeTime: lifetime, + EmailAttr: emailattr, + Key: key, + UserID: userID, + ContainerID: containerID, + LifeTime: lifetime, + MaxObjectSize: maxObjectSize, + ObjectMaxLifetime: objectMaxLifetime, }, BearerCookieName: bearerCookieName, Oauth: make(map[string]*auth.ServiceOauth), diff --git a/cmd/neofs-oauthz/config.go b/cmd/neofs-oauthz/config.go index 03ad474..c843039 100644 --- a/cmd/neofs-oauthz/config.go +++ b/cmd/neofs-oauthz/config.go @@ -13,12 +13,14 @@ import ( ) const ( - defaultEmailAttr = "Email" - defaultBearerCookieName = "Bearer" - defaultBearerLifetime = 30 - defaultConnectTimeout = 30 * time.Second - defaultRebalanceTimer = 15 * time.Second - defaultRequestTimeout = 15 * time.Second + defaultEmailAttr = "Email" + defaultBearerCookieName = "Bearer" + defaultBearerLifetime = 30 // epochs + defaultMaxObjectSize = 200 << 20 // 200MB + defaultMaxObjectLifetime = 4 * 24 * time.Hour // 4 days + defaultConnectTimeout = 30 * time.Second + defaultRebalanceTimer = 15 * time.Second + defaultRequestTimeout = 15 * time.Second defaultListenAddress = "0.0.0.0:8083" @@ -28,13 +30,15 @@ const ( cfgTLSCertificate = "tls_certificate" cfgTLSKey = "tls_key" - cfgContainerID = "neofs.cid" - cfgEmailAttr = "neofs.bearer_email_attribute" - cfgUserID = "neofs.bearer_user_id" - cfgBearerLifetime = "neofs.bearer_lifetime" - cfgNeoFSWalletPath = "neofs.wallet.path" - cfgNeoFSWalletPassphrase = "neofs.wallet.passphrase" - cfgNeoFSWalletAddress = "neofs.wallet.address" + cfgContainerID = "neofs.cid" + cfgEmailAttr = "neofs.bearer_email_attribute" + cfgUserID = "neofs.bearer_user_id" + cfgBearerLifetime = "neofs.bearer_lifetime" + cfgBearerMaxObjectSize = "neofs.max_object_size" + cfgBearerMaxObjectLifetime = "neofs.max_object_lifetime" + cfgNeoFSWalletPath = "neofs.wallet.path" + cfgNeoFSWalletPassphrase = "neofs.wallet.passphrase" + cfgNeoFSWalletAddress = "neofs.wallet.address" cfgPeers = "peers" diff --git a/config/config.yaml b/config/config.yaml index cfcc04d..38e6eb6 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -24,6 +24,8 @@ neofs: passphrase: '' # Passphrase to decrypt wallet. If you're using a wallet without a password, place '' here. address: NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP # Account address. If omitted default one will be used. cid: 2qAEwyRwV1sMmq8pc32mKCt1SRmTBXrzP9KbfMoHmqYM + max_object_size: 209715200 # max object size allowed to be deployed via bearer token. 200mb. + max_object_lifetime: "96h" # max object lifetime. 4 days. peers: 0: diff --git a/go.mod b/go.mod index 46eaa17..83b5c82 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/nspcc-dev/neo-go v0.105.1 - github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240222163622-e29215027193 + github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240419132800-d0208992bf00 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.18.2 go.uber.org/zap v1.27.0 @@ -25,8 +25,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/nspcc-dev/hrw/v2 v2.0.1 // indirect - github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240213170208-cfca09b5acbe // indirect - github.com/nspcc-dev/neofs-crypto v0.4.1 // indirect + github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240305074711-35bc78d84dc4 // indirect github.com/nspcc-dev/rfc6979 v0.2.1 // indirect github.com/nspcc-dev/tzhash v1.7.2 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect diff --git a/go.sum b/go.sum index f75aef6..3a963e4 100644 --- a/go.sum +++ b/go.sum @@ -18,7 +18,7 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -61,12 +61,10 @@ github.com/nspcc-dev/hrw/v2 v2.0.1 h1:CxYUkBeJvNfMEn2lHhrV6FjY8pZPceSxXUtMVq0BUO github.com/nspcc-dev/hrw/v2 v2.0.1/go.mod h1:iZAs5hT2q47EGq6AZ0FjaUI6ggntOi7vrY4utfzk5VA= github.com/nspcc-dev/neo-go v0.105.1 h1:r0b2yIwLBi+ARBKU94gHL9oTFEB/XMJ0YlS2HN9Qw34= github.com/nspcc-dev/neo-go v0.105.1/go.mod h1:GNh0cRALV/cuj+/xg2ZHDsrFbqcInqG7jjhqsLEnlNc= -github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240213170208-cfca09b5acbe h1:Hoq88+PWS6tNnX4Y0jxE0C8wvxPI8UlVnCs2ZJDEy4Y= -github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240213170208-cfca09b5acbe/go.mod h1:eaffSBIGhXUIMYvRBGXmlgQRLyyCWlzOft9jGYlqwrw= -github.com/nspcc-dev/neofs-crypto v0.4.1 h1:B6S0zXMWrVFlf/GlII6xKRGWU0VE7dHM+QkoKAO7AQA= -github.com/nspcc-dev/neofs-crypto v0.4.1/go.mod h1:0SHn+sSn+lrrIvonLR8MgbOlBhXZKhc4rw/l2htYeA0= -github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240222163622-e29215027193 h1:U+HfAuitCuoebTfGcjb8Gxs4NvpBaYQ1RYClkV1oF64= -github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240222163622-e29215027193/go.mod h1:GED7qcgut188OQYY7lak/cGN8DHtjqQbrXdSt/82QNE= +github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240305074711-35bc78d84dc4 h1:arN0Ypn+jawZpu1BND7TGRn44InAVIqKygndsx0y2no= +github.com/nspcc-dev/neofs-api-go/v2 v2.14.1-0.20240305074711-35bc78d84dc4/go.mod h1:7Tm1NKEoUVVIUlkVwFrPh7GG5+Lmta2m7EGr4oVpBd8= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240419132800-d0208992bf00 h1:jr1P1DgK+Y2IV/QQeTD2SllNbucaOw9U1I0ikWEwgUE= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11.0.20240419132800-d0208992bf00/go.mod h1:AApSmHoQ6o/4bz6Am2RmfX0mdgCTEPDDXpV/g4OFOlE= github.com/nspcc-dev/rfc6979 v0.2.1 h1:8wWxkamHWFmO790GsewSoKUSJjVnL1fmdRpokU/RgRM= github.com/nspcc-dev/rfc6979 v0.2.1/go.mod h1:Tk7h5kyUWkhjyO3zUgFFhy1v2vQv3BvQEntakdtqrWc= github.com/nspcc-dev/tzhash v1.7.2 h1:iRXoa9TJqH/DQO7FFcqpq9BdruF9E7/xnFGlIghl5J4=