Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [1.22.x]
go-version: [1.24.x]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.22.7
go-version: 1.24.6
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion buildscripts/cross-compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function _build() {

# go build -trimpath to build the binary.
if [ "${CAN_BUILD_WITHOUT_DOCKER}" == "false" ]; then
docker run --name runner -d -v $PWD:$PWD --workdir $PWD golang:1.22 sleep infinity
docker run --name runner -d -v $PWD:$PWD --workdir $PWD golang:1.24.6 sleep infinity
docker exec -t runner git config --global --add safe.directory $PWD
docker exec -t runner go build -trimpath -tags kqueue --ldflags "${LDFLAGS}" -o "./bin/minio_${os}_${arch}" 1>/dev/null
MUID=$(id -u)
Expand Down
24 changes: 20 additions & 4 deletions cmd/admin-handlers-users.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,10 +598,26 @@ func (a adminAPIHandlers) UpdateServiceAccount(w http.ResponseWriter, r *http.Re
return
}

// Disallow editing service accounts by root user.
if owner {
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAdminAccountNotEligible), r.URL)
return
// Only users with UpdateServiceAccountAdminAction may edit service accounts.
if !globalIAMSys.IsAllowed(iampolicy.Args{
AccountName: cred.AccessKey,
Action: iampolicy.UpdateServiceAccountAdminAction,
ConditionValues: getConditionValues(r, "", cred.AccessKey, claims),
IsOwner: owner,
Claims: claims,
}) {
// Fallback: allow parent user to edit their own service accounts
// to maintain backward compatibility.
requestUser := cred.AccessKey
if cred.ParentUser != "" {
requestUser = cred.ParentUser
}

svcAccount, _, err := globalIAMSys.GetServiceAccount(ctx, mux.Vars(r)["accessKey"])
if err != nil || requestUser != svcAccount.ParentUser {
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL)
return
}
}

svcAccount, _, err := globalIAMSys.GetServiceAccount(ctx, accessKey)
Expand Down
2 changes: 1 addition & 1 deletion cmd/config-encrypted.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/madmin"
etcd "go.etcd.io/etcd/clientv3"
etcd "go.etcd.io/etcd/client/v3"
)

func handleEncryptedConfigBackend(objAPI ObjectLayer) error {
Expand Down
2 changes: 1 addition & 1 deletion cmd/config/dns/etcd_dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (

"github.com/coredns/coredns/plugin/etcd/msg"
"github.com/minio/minio-go/v7/pkg/set"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/client/v3"
)

// ErrNoEntriesFound - Indicates no entries were found for the given key (directory)
Expand Down
2 changes: 1 addition & 1 deletion cmd/config/dns/operator_dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"strings"
"time"

"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt/v4"
"github.com/minio/minio/cmd/config"
xhttp "github.com/minio/minio/cmd/http"
)
Expand Down
4 changes: 2 additions & 2 deletions cmd/config/etcd/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import (
"github.com/minio/minio/cmd/config"
"github.com/minio/minio/pkg/env"
xnet "github.com/minio/minio/pkg/net"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/clientv3/namespace"
"go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/client/v3/namespace"
"go.uber.org/zap"
)

Expand Down
2 changes: 1 addition & 1 deletion cmd/config/identity/openid/ecdsa-sha3.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package openid
import (
"crypto"

"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt/v4"

// Needed for SHA3 to work - See: https://golang.org/src/crypto/crypto.go?s=1034:1288
_ "golang.org/x/crypto/sha3" // There is no SHA-3 FIPS-140 2 compliant implementation
Expand Down
2 changes: 1 addition & 1 deletion cmd/config/identity/openid/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"sync"
"time"

jwtgo "github.com/dgrijalva/jwt-go"
jwtgo "github.com/golang-jwt/jwt/v4"
"github.com/minio/minio/cmd/config"
"github.com/minio/minio/pkg/auth"
"github.com/minio/minio/pkg/env"
Expand Down
2 changes: 1 addition & 1 deletion cmd/config/identity/openid/rsa-sha3.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package openid
import (
"crypto"

"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt/v4"

// Needed for SHA3 to work - See: https://golang.org/src/crypto/crypto.go?s=1034:1288
_ "golang.org/x/crypto/sha3" // There is no SHA-3 FIPS-140 2 compliant implementation
Expand Down
2 changes: 1 addition & 1 deletion cmd/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"errors"
"fmt"

etcd "go.etcd.io/etcd/clientv3"
etcd "go.etcd.io/etcd/client/v3"
)

var errEtcdUnreachable = errors.New("etcd is unreachable, please check your endpoints")
Expand Down
2 changes: 1 addition & 1 deletion cmd/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (
"github.com/minio/minio/cmd/config/storageclass"
xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/pkg/auth"
etcd "go.etcd.io/etcd/clientv3"
etcd "go.etcd.io/etcd/client/v3"

"github.com/minio/minio/pkg/certs"
"github.com/minio/minio/pkg/event"
Expand Down
3 changes: 3 additions & 0 deletions cmd/http/headers.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ const (
AmzSecurityToken = "X-Amz-Security-Token"
AmzDecodedContentLength = "X-Amz-Decoded-Content-Length"

// S3 trailers extension
AmzTrailer = "X-Amz-Trailer"

AmzMetaUnencryptedContentLength = "X-Amz-Meta-X-Amz-Unencrypted-Content-Length"
AmzMetaUnencryptedContentMD5 = "X-Amz-Meta-X-Amz-Unencrypted-Content-Md5"

Expand Down
15 changes: 8 additions & 7 deletions cmd/iam-etcd-store.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ import (
"time"
"unicode/utf8"

jwtgo "github.com/dgrijalva/jwt-go"
jwtgo "github.com/golang-jwt/jwt/v4"
"github.com/minio/minio-go/v7/pkg/set"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
iampolicy "github.com/minio/minio/pkg/iam/policy"
"github.com/minio/minio/pkg/madmin"
etcd "go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/mvcc/mvccpb"
"go.etcd.io/etcd/api/v3/mvccpb"
etcd "go.etcd.io/etcd/client/v3"
)

var defaultContextTimeout = 30 * time.Second
Expand All @@ -50,10 +50,11 @@ func etcdKvsToSet(prefix string, kvs []*mvccpb.KeyValue) set.StringSet {

// Extract path string by stripping off the `prefix` value and the suffix,
// value, usually in the following form.
// s := "config/iam/users/foo/config.json"
// prefix := "config/iam/users/"
// suffix := "config.json"
// result is foo
//
// s := "config/iam/users/foo/config.json"
// prefix := "config/iam/users/"
// suffix := "config.json"
// result is foo
func extractPathPrefixAndSuffix(s string, prefix string, suffix string) string {
return pathClean(strings.TrimSuffix(strings.TrimPrefix(string(s), prefix), suffix))
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/iam-object-store.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"time"
"unicode/utf8"

jwtgo "github.com/dgrijalva/jwt-go"
jwtgo "github.com/golang-jwt/jwt/v4"

"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
Expand Down
4 changes: 2 additions & 2 deletions cmd/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import (
"net/http"
"time"

jwtgo "github.com/dgrijalva/jwt-go"
jwtreq "github.com/dgrijalva/jwt-go/request"
jwtgo "github.com/golang-jwt/jwt/v4"
jwtreq "github.com/golang-jwt/jwt/v4/request"
xjwt "github.com/minio/minio/cmd/jwt"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/auth"
Expand Down
2 changes: 1 addition & 1 deletion cmd/jwt/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
"sync"
"time"

jwtgo "github.com/dgrijalva/jwt-go"
jwtgo "github.com/golang-jwt/jwt/v4"
jsoniter "github.com/json-iterator/go"
)

Expand Down
2 changes: 1 addition & 1 deletion cmd/jwt/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"testing"
"time"

"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt/v4"
)

var (
Expand Down
47 changes: 27 additions & 20 deletions cmd/object-handlers-common.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,22 @@ var (

// Validates the preconditions for CopyObjectPart, returns true if CopyObjectPart
// operation should not proceed. Preconditions supported are:
// x-amz-copy-source-if-modified-since
// x-amz-copy-source-if-unmodified-since
// x-amz-copy-source-if-match
// x-amz-copy-source-if-none-match
//
// x-amz-copy-source-if-modified-since
// x-amz-copy-source-if-unmodified-since
// x-amz-copy-source-if-match
// x-amz-copy-source-if-none-match
func checkCopyObjectPartPreconditions(ctx context.Context, w http.ResponseWriter, r *http.Request, objInfo ObjectInfo) bool {
return checkCopyObjectPreconditions(ctx, w, r, objInfo)
}

// Validates the preconditions for CopyObject, returns true if CopyObject operation should not proceed.
// Preconditions supported are:
// x-amz-copy-source-if-modified-since
// x-amz-copy-source-if-unmodified-since
// x-amz-copy-source-if-match
// x-amz-copy-source-if-none-match
//
// x-amz-copy-source-if-modified-since
// x-amz-copy-source-if-unmodified-since
// x-amz-copy-source-if-match
// x-amz-copy-source-if-none-match
func checkCopyObjectPreconditions(ctx context.Context, w http.ResponseWriter, r *http.Request, objInfo ObjectInfo) bool {
// Return false for methods other than GET and HEAD.
if r.Method != http.MethodPut {
Expand All @@ -66,10 +68,11 @@ func checkCopyObjectPreconditions(ctx context.Context, w http.ResponseWriter, r
setCommonHeaders(w)

// set object-related metadata headers
w.Header().Set(xhttp.LastModified, objInfo.ModTime.UTC().Format(http.TimeFormat))

if objInfo.ETag != "" {
w.Header()[xhttp.ETag] = []string{"\"" + objInfo.ETag + "\""}
if getRequestAuthType(r) != authTypeAnonymous {
w.Header().Set(xhttp.LastModified, objInfo.ModTime.UTC().Format(http.TimeFormat))
if objInfo.ETag != "" {
w.Header()[xhttp.ETag] = []string{"\"" + objInfo.ETag + "\""}
}
}
}
// x-amz-copy-source-if-modified-since: Return the object only if it has been modified
Expand Down Expand Up @@ -129,10 +132,11 @@ func checkCopyObjectPreconditions(ctx context.Context, w http.ResponseWriter, r

// Validates the preconditions. Returns true if GET/HEAD operation should not proceed.
// Preconditions supported are:
// If-Modified-Since
// If-Unmodified-Since
// If-Match
// If-None-Match
//
// If-Modified-Since
// If-Unmodified-Since
// If-Match
// If-None-Match
func checkPreconditions(ctx context.Context, w http.ResponseWriter, r *http.Request, objInfo ObjectInfo, opts ObjectOptions) bool {
// Return false for methods other than GET and HEAD.
if r.Method != http.MethodGet && r.Method != http.MethodHead {
Expand All @@ -151,10 +155,13 @@ func checkPreconditions(ctx context.Context, w http.ResponseWriter, r *http.Requ
setCommonHeaders(w)

// set object-related metadata headers
w.Header().Set(xhttp.LastModified, objInfo.ModTime.UTC().Format(http.TimeFormat))

if objInfo.ETag != "" {
w.Header()[xhttp.ETag] = []string{"\"" + objInfo.ETag + "\""}
// Only add Last-Modified/ETag for authenticated requests. Anonymous
// requests should not learn object existence/metadata via preconditions.
if getRequestAuthType(r) != authTypeAnonymous {
w.Header().Set(xhttp.LastModified, objInfo.ModTime.UTC().Format(http.TimeFormat))
if objInfo.ETag != "" {
w.Header()[xhttp.ETag] = []string{"\"" + objInfo.ETag + "\""}
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions cmd/signature-v4-utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ func checkKeyValid(accessKey string) (auth.Credentials, bool, APIErrorCode) {
}
owner = false
}
// Service accounts must always be validated with a session token.
// Reject bare access-key usage for service accounts.
if cred.IsServiceAccount() {
return cred, owner, ErrInvalidToken
}
return cred, owner, ErrNone
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/storage-rest-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (

"github.com/tinylib/msgp/msgp"

jwtreq "github.com/dgrijalva/jwt-go/request"
jwtreq "github.com/golang-jwt/jwt/v4/request"
"github.com/gorilla/mux"
"github.com/minio/minio/cmd/config"
xhttp "github.com/minio/minio/cmd/http"
Expand Down
12 changes: 10 additions & 2 deletions cmd/streaming-signature-v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ func getChunkSignature(cred auth.Credentials, seedSignature string, region strin
}

// calculateSeedSignature - Calculate seed signature in accordance with
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html
//
// returns signature, error otherwise if the signature mismatches or any other
// error while parsing and validating.
func calculateSeedSignature(r *http.Request) (cred auth.Credentials, signature string, region string, date time.Time, errCode APIErrorCode) {
Expand Down Expand Up @@ -154,6 +155,12 @@ var errMalformedEncoding = errors.New("malformed chunked encoding")
// NewChunkedReader is not needed by normal applications. The http package
// automatically decodes chunking when reading response bodies.
func newSignV4ChunkedReader(req *http.Request) (io.ReadCloser, APIErrorCode) {
// Reject unsigned-trailer uploads. If client indicates trailers but did not
// sign them as part of the payload, this can lead to signature bypass.
// Only allow when X-Amz-Trailer is absent.
if req.Header.Get(xhttp.AmzTrailer) != "" {
return nil, ErrSignatureDoesNotMatch
}
cred, seedSignature, region, seedDate, errCode := calculateSeedSignature(req)
if errCode != ErrNone {
return nil, errCode
Expand Down Expand Up @@ -409,7 +416,8 @@ const s3ChunkSignatureStr = ";chunk-signature="

// parses3ChunkExtension removes any s3 specific chunk-extension from buf.
// For example,
// "10000;chunk-signature=..." => "10000", "chunk-signature=..."
//
// "10000;chunk-signature=..." => "10000", "chunk-signature=..."
func parseS3ChunkExtension(buf []byte) ([]byte, []byte) {
buf = trimTrailingWhitespace(buf)
semi := bytes.Index(buf, []byte(s3ChunkSignatureStr))
Expand Down
2 changes: 1 addition & 1 deletion cmd/web-handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
"strings"
"testing"

jwtgo "github.com/dgrijalva/jwt-go"
jwtgo "github.com/golang-jwt/jwt/v4"
humanize "github.com/dustin/go-humanize"
xjwt "github.com/minio/minio/cmd/jwt"
"github.com/minio/minio/pkg/hash"
Expand Down
Loading