mirror of
https://github.com/pgsty/minio.git
synced 2026-08-09 15:53:28 +03:00
fix(iam): enforce the bucket/object resource boundary
Upgrade directly to silo-pkg v3.11.0, the fork's first non-colliding release, and carry the completed minio/minio#20449 hardening without exposing the retired v3.7.0, v3.8.0, or v3.8.1 tags in the rewritten history. Twelve sensitive bucket-level writes now require the bare bucket resource in addition to the historical bucket/ form, so an object-only bucket/* grant cannot delete a bucket or change protections. Read/list behavior, ordinary tenant self-service, Deny statements, and NotResource exclusions retain their compatible behavior; MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH restores the old matcher when migration requires it. End-to-end tests cover direct clients, session policies, service accounts, wildcard edge cases, compatible resource pairs, and real bucket deletion. Co-authored-by: ChatGPT <noreply@openai.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,379 @@
|
|||||||
|
// Copyright (c) 2015-2026 MinIO, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of MinIO Object Storage stack
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/minio/madmin-go/v3"
|
||||||
|
"github.com/minio/minio-go/v7"
|
||||||
|
"github.com/minio/minio/internal/auth"
|
||||||
|
"github.com/minio/pkg/v3/policy"
|
||||||
|
)
|
||||||
|
|
||||||
|
// These tests pin the IAM bucket/object resource boundary end to end, through
|
||||||
|
// the real handlers rather than the matcher alone. An object-only resource
|
||||||
|
// pattern ("arn:aws:s3:::bucket/*") must not authorize the bucket-level writes
|
||||||
|
// that hand a caller something its object access does not already provide —
|
||||||
|
// upstream minio/minio issue #20449 — while every shape the fix deliberately
|
||||||
|
// leaves alone keeps working. Both directions are asserted, because a change
|
||||||
|
// here that only removes permissions is correct and one that adds any is not.
|
||||||
|
|
||||||
|
// A bucket-level write reached only through an object-only grant must be
|
||||||
|
// refused, and refusing it must not destroy the bucket. A grant that names the
|
||||||
|
// bucket must still succeed, and succeeding must actually remove it.
|
||||||
|
func assertBucketDelete(ctx context.Context, c *check, admin, client *minio.Client, bucket string, wantAllowed bool) {
|
||||||
|
c.Helper()
|
||||||
|
err := client.RemoveBucket(ctx, bucket)
|
||||||
|
if wantAllowed {
|
||||||
|
if err != nil {
|
||||||
|
c.Fatalf("RemoveBucket(%s) denied, want allowed: %v", bucket, err)
|
||||||
|
}
|
||||||
|
exists, existsErr := admin.BucketExists(ctx, bucket)
|
||||||
|
if existsErr != nil {
|
||||||
|
c.Fatalf("check removed bucket %s: %v", bucket, existsErr)
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
c.Fatalf("RemoveBucket(%s) returned nil but bucket still exists", bucket)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
c.Fatalf("RemoveBucket(%s) returned nil, want AccessDenied", bucket)
|
||||||
|
}
|
||||||
|
if response := minio.ToErrorResponse(err); response.Code != "AccessDenied" {
|
||||||
|
c.Fatalf("RemoveBucket(%s) error code=%q, want AccessDenied (err=%v)", bucket, response.Code, err)
|
||||||
|
}
|
||||||
|
exists, existsErr := admin.BucketExists(ctx, bucket)
|
||||||
|
if existsErr != nil {
|
||||||
|
c.Fatalf("check protected bucket %s: %v", bucket, existsErr)
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
c.Fatalf("RemoveBucket(%s) returned AccessDenied but bucket disappeared", bucket)
|
||||||
|
}
|
||||||
|
if err := admin.RemoveBucket(ctx, bucket); err != nil {
|
||||||
|
c.Fatalf("cleanup protected bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createUserWithPolicy(ctx context.Context, c *check, s *TestSuiteIAM, policyJSON []byte) (*minio.Client, string) {
|
||||||
|
c.Helper()
|
||||||
|
accessKey, secretKey := mustGenerateCredentials(c)
|
||||||
|
if err := s.adm.SetUser(ctx, accessKey, secretKey, madmin.AccountEnabled); err != nil {
|
||||||
|
c.Fatalf("set boundary user: %v", err)
|
||||||
|
}
|
||||||
|
policyName := "boundary-" + mustGetUUID()
|
||||||
|
if err := s.adm.AddCannedPolicy(ctx, policyName, policyJSON); err != nil {
|
||||||
|
c.Fatalf("add boundary policy: %v", err)
|
||||||
|
}
|
||||||
|
if _, err := s.adm.AttachPolicy(ctx, madmin.PolicyAssociationReq{
|
||||||
|
Policies: []string{policyName},
|
||||||
|
User: accessKey,
|
||||||
|
}); err != nil {
|
||||||
|
c.Fatalf("attach boundary policy: %v", err)
|
||||||
|
}
|
||||||
|
return s.getUserClient(c, accessKey, secretKey, ""), accessKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBucketResourceBoundaryEndToEnd(t *testing.T) {
|
||||||
|
if runtime.GOOS == globalWindowsOSName {
|
||||||
|
t.Skip("IAM integration harness is disabled on Windows")
|
||||||
|
}
|
||||||
|
suite := newTestSuiteIAM(TestSuiteCommon{serverType: "ErasureSD", signer: signerV4}, false)
|
||||||
|
c := &check{t, suite.serverType}
|
||||||
|
suite.SetUpSuite(c)
|
||||||
|
defer suite.TearDownSuite(c)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// The #20449 reproduction: "s3:*" on "bucket/*" and nothing else.
|
||||||
|
coreBucket := getRandomBucketName()
|
||||||
|
if err := suite.client.MakeBucket(ctx, coreBucket, minio.MakeBucketOptions{}); err != nil {
|
||||||
|
c.Fatalf("create core bucket: %v", err)
|
||||||
|
}
|
||||||
|
corePolicy := fmt.Appendf(nil, `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::%s/*"}]
|
||||||
|
}`, coreBucket)
|
||||||
|
coreClient, _ := createUserWithPolicy(ctx, c, suite, corePolicy)
|
||||||
|
assertBucketDelete(ctx, c, suite.client, coreClient, coreBucket, false)
|
||||||
|
|
||||||
|
// The conventional pairing of bucket and object ARNs stays authorized.
|
||||||
|
pairedBucket := getRandomBucketName()
|
||||||
|
if err := suite.client.MakeBucket(ctx, pairedBucket, minio.MakeBucketOptions{}); err != nil {
|
||||||
|
c.Fatalf("create paired bucket: %v", err)
|
||||||
|
}
|
||||||
|
pairedPolicy := fmt.Appendf(nil, `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","Resource":[
|
||||||
|
"arn:aws:s3:::%s","arn:aws:s3:::%s/*"
|
||||||
|
]}]
|
||||||
|
}`, pairedBucket, pairedBucket)
|
||||||
|
pairedClient, _ := createUserWithPolicy(ctx, c, suite, pairedPolicy)
|
||||||
|
assertBucketDelete(ctx, c, suite.client, pairedClient, pairedBucket, true)
|
||||||
|
|
||||||
|
// CreateBucket and ListBucket keep the historical object-pattern matching.
|
||||||
|
compatBucket := getRandomBucketName()
|
||||||
|
compatPolicy := fmt.Appendf(nil, `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::%s/*"}]
|
||||||
|
}`, compatBucket)
|
||||||
|
compatClient, _ := createUserWithPolicy(ctx, c, suite, compatPolicy)
|
||||||
|
if err := compatClient.MakeBucket(ctx, compatBucket, minio.MakeBucketOptions{}); err != nil {
|
||||||
|
c.Fatalf("CreateBucket compatibility path denied: %v", err)
|
||||||
|
}
|
||||||
|
for item := range compatClient.ListObjects(ctx, compatBucket, minio.ListObjectsOptions{}) {
|
||||||
|
if item.Err != nil {
|
||||||
|
c.Fatalf("ListBucket compatibility path denied: %v", item.Err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := suite.client.RemoveBucket(ctx, compatBucket); err != nil {
|
||||||
|
c.Fatalf("cleanup compatibility bucket: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Withholding the trailing slash changes the string patterns match against,
|
||||||
|
// so a fixed-width wildcard can match the bare bucket name without ever
|
||||||
|
// having matched "bucket/". Honoring it would GRANT a delete the historical
|
||||||
|
// matcher refused, which the hardening must never do.
|
||||||
|
wildcardBucket := getRandomBucketName()
|
||||||
|
if err := suite.client.MakeBucket(ctx, wildcardBucket, minio.MakeBucketOptions{}); err != nil {
|
||||||
|
c.Fatalf("create fixed-width wildcard bucket: %v", err)
|
||||||
|
}
|
||||||
|
wildcardPolicy := fmt.Appendf(nil, `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:DeleteBucket","Resource":"arn:aws:s3:::%s?"}]
|
||||||
|
}`, wildcardBucket[:len(wildcardBucket)-1])
|
||||||
|
wildcardClient, _ := createUserWithPolicy(ctx, c, suite, wildcardPolicy)
|
||||||
|
assertBucketDelete(ctx, c, suite.client, wildcardClient, wildcardBucket, false)
|
||||||
|
|
||||||
|
// A NotResource exclusion keeps its historical reach, so narrowing it — and
|
||||||
|
// thereby broadening the Allow it qualifies — cannot happen unnoticed.
|
||||||
|
notResourceBucket := getRandomBucketName()
|
||||||
|
if err := suite.client.MakeBucket(ctx, notResourceBucket, minio.MakeBucketOptions{}); err != nil {
|
||||||
|
c.Fatalf("create NotResource bucket: %v", err)
|
||||||
|
}
|
||||||
|
notResourcePolicy := fmt.Appendf(nil, `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","NotResource":"arn:aws:s3:::%s/*"}]
|
||||||
|
}`, notResourceBucket)
|
||||||
|
notResourceClient, _ := createUserWithPolicy(ctx, c, suite, notResourcePolicy)
|
||||||
|
assertBucketDelete(ctx, c, suite.client, notResourceClient, notResourceBucket, false)
|
||||||
|
|
||||||
|
// A Deny written against "bucket/*" keeps covering the bucket-level request.
|
||||||
|
denyBucket := getRandomBucketName()
|
||||||
|
if err := suite.client.MakeBucket(ctx, denyBucket, minio.MakeBucketOptions{}); err != nil {
|
||||||
|
c.Fatalf("create Deny bucket: %v", err)
|
||||||
|
}
|
||||||
|
denyPolicy := fmt.Appendf(nil, `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[
|
||||||
|
{"Effect":"Allow","Action":"s3:*","Resource":"*"},
|
||||||
|
{"Effect":"Deny","Action":"s3:DeleteBucket","Resource":"arn:aws:s3:::%s/*"}
|
||||||
|
]
|
||||||
|
}`, denyBucket)
|
||||||
|
denyClient, _ := createUserWithPolicy(ctx, c, suite, denyPolicy)
|
||||||
|
assertBucketDelete(ctx, c, suite.client, denyClient, denyBucket, false)
|
||||||
|
|
||||||
|
// A service account whose parent policy allows everything but whose inline
|
||||||
|
// policy is object-only exercises the nested AND evaluation path, where the
|
||||||
|
// boundary has to hold on the inline side.
|
||||||
|
serviceBucket := getRandomBucketName()
|
||||||
|
if err := suite.client.MakeBucket(ctx, serviceBucket, minio.MakeBucketOptions{}); err != nil {
|
||||||
|
c.Fatalf("create service-account bucket: %v", err)
|
||||||
|
}
|
||||||
|
parentPolicy := []byte(`{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","Resource":"*"}]
|
||||||
|
}`)
|
||||||
|
_, parentUser := createUserWithPolicy(ctx, c, suite, parentPolicy)
|
||||||
|
servicePolicy := fmt.Appendf(nil, `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::%s/*"}]
|
||||||
|
}`, serviceBucket)
|
||||||
|
serviceAccess, serviceSecret := mustGenerateCredentials(c)
|
||||||
|
serviceAccount, err := suite.adm.AddServiceAccount(ctx, madmin.AddServiceAccountReq{
|
||||||
|
TargetUser: parentUser,
|
||||||
|
AccessKey: serviceAccess,
|
||||||
|
SecretKey: serviceSecret,
|
||||||
|
Policy: bytes.Clone(servicePolicy),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.Fatalf("create restricted service account: %v", err)
|
||||||
|
}
|
||||||
|
serviceClient := suite.getUserClient(c, serviceAccount.AccessKey, serviceAccount.SecretKey, "")
|
||||||
|
assertBucketDelete(ctx, c, suite.client, serviceClient, serviceBucket, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The same boundary, asserted against an inline session policy evaluated
|
||||||
|
// directly, so a regression in the STS and service-account paths is caught even
|
||||||
|
// if the integration harness above is skipped.
|
||||||
|
func TestBucketResourceBoundaryInlineSessionPolicy(t *testing.T) {
|
||||||
|
inline := `{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": "s3:*",
|
||||||
|
"Resource": "arn:aws:s3:::mybucket/*"
|
||||||
|
}]
|
||||||
|
}`
|
||||||
|
args := policy.Args{
|
||||||
|
Action: policy.DeleteBucketAction,
|
||||||
|
BucketName: "mybucket",
|
||||||
|
Claims: map[string]any{
|
||||||
|
sessionPolicyNameExtracted: inline,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, evaluate := range map[string]func(policy.Args) (bool, bool){
|
||||||
|
"STS inline policy": isAllowedBySessionPolicy,
|
||||||
|
"service-account inline policy": isAllowedBySessionPolicyForServiceAccount,
|
||||||
|
} {
|
||||||
|
hasPolicy, allowed := evaluate(args)
|
||||||
|
if !hasPolicy {
|
||||||
|
t.Errorf("%s was not detected", name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if allowed {
|
||||||
|
t.Errorf("%s authorized DeleteBucket through an object-only resource", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The boundary driven through the real S3 router and DeleteBucket handler,
|
||||||
|
// without opening a TCP listener.
|
||||||
|
func TestBucketResourceBoundaryHandler(t *testing.T) {
|
||||||
|
ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{
|
||||||
|
t: t,
|
||||||
|
endpoints: nil, // Register the full router; the focused list omits DeleteBucket.
|
||||||
|
objAPITest: func(obj ObjectLayer, instanceType, _ string, apiRouter http.Handler, _ auth.Credentials, t *testing.T) {
|
||||||
|
ctx := t.Context()
|
||||||
|
if !globalReplicationPool.IsSet() {
|
||||||
|
// Match initTestServerWithBackend: DeleteBucket calls through this
|
||||||
|
// singleton after the object-layer deletion, and a nil receiver is safe.
|
||||||
|
globalReplicationPool.Set(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
newPolicyClient := func(policyJSON string) auth.Credentials {
|
||||||
|
t.Helper()
|
||||||
|
accessKey, secretKey, err := auth.GenerateCredentials()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
credentials := auth.Credentials{AccessKey: accessKey, SecretKey: secretKey}
|
||||||
|
if _, err = globalIAMSys.CreateUser(ctx, credentials.AccessKey, madmin.AddOrUpdateUserReq{
|
||||||
|
SecretKey: credentials.SecretKey,
|
||||||
|
Status: madmin.AccountEnabled,
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatalf("%s: create boundary user: %v", instanceType, err)
|
||||||
|
}
|
||||||
|
parsed, err := policy.ParseConfig(strings.NewReader(policyJSON))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s: parse boundary policy: %v", instanceType, err)
|
||||||
|
}
|
||||||
|
policyName := "boundary-" + mustGetUUID()
|
||||||
|
if _, err = globalIAMSys.SetPolicy(ctx, policyName, *parsed); err != nil {
|
||||||
|
t.Fatalf("%s: install boundary policy: %v", instanceType, err)
|
||||||
|
}
|
||||||
|
if _, err = globalIAMSys.PolicyDBSet(ctx, credentials.AccessKey, policyName, regUser, false); err != nil {
|
||||||
|
t.Fatalf("%s: attach boundary policy: %v", instanceType, err)
|
||||||
|
}
|
||||||
|
return credentials
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteCase := func(label, policyJSON string, wantAllowed bool) {
|
||||||
|
t.Helper()
|
||||||
|
bucket := getRandomBucketName()
|
||||||
|
if err := obj.MakeBucket(ctx, bucket, MakeBucketOptions{}); err != nil {
|
||||||
|
t.Fatalf("%s/%s: create bucket: %v", instanceType, label, err)
|
||||||
|
}
|
||||||
|
policyJSON = strings.ReplaceAll(policyJSON, "BUCKET_WILDCARD", bucket[:len(bucket)-1]+"?")
|
||||||
|
policyJSON = strings.ReplaceAll(policyJSON, "BUCKET", bucket)
|
||||||
|
credentials := newPolicyClient(policyJSON)
|
||||||
|
req, err := newTestSignedRequestV4(http.MethodDelete, getDeleteBucketURL("", bucket),
|
||||||
|
0, nil, credentials.AccessKey, credentials.SecretKey, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s/%s: sign DeleteBucket: %v", instanceType, label, err)
|
||||||
|
}
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
apiRouter.ServeHTTP(recorder, req)
|
||||||
|
|
||||||
|
if wantAllowed {
|
||||||
|
if recorder.Code != http.StatusNoContent {
|
||||||
|
t.Fatalf("%s/%s: DeleteBucket status=%d body=%s, want 204",
|
||||||
|
instanceType, label, recorder.Code, recorder.Body.String())
|
||||||
|
}
|
||||||
|
if _, err = obj.GetBucketInfo(ctx, bucket, BucketOptions{}); err == nil {
|
||||||
|
t.Fatalf("%s/%s: handler returned 204 but bucket still exists", instanceType, label)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if recorder.Code != http.StatusForbidden || !strings.Contains(recorder.Body.String(), "AccessDenied") {
|
||||||
|
t.Fatalf("%s/%s: DeleteBucket status=%d body=%s, want AccessDenied",
|
||||||
|
instanceType, label, recorder.Code, recorder.Body.String())
|
||||||
|
}
|
||||||
|
if _, err = obj.GetBucketInfo(ctx, bucket, BucketOptions{}); err != nil {
|
||||||
|
t.Fatalf("%s/%s: denied bucket disappeared: %v", instanceType, label, err)
|
||||||
|
}
|
||||||
|
if err = obj.DeleteBucket(ctx, bucket, DeleteBucketOptions{}); err != nil {
|
||||||
|
t.Fatalf("%s/%s: cleanup bucket: %v", instanceType, label, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteCase("object-only s3:*", `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","Resource":"arn:aws:s3:::BUCKET/*"}]
|
||||||
|
}`, false)
|
||||||
|
|
||||||
|
deleteCase("paired resource", `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","Resource":[
|
||||||
|
"arn:aws:s3:::BUCKET","arn:aws:s3:::BUCKET/*"
|
||||||
|
]}]
|
||||||
|
}`, true)
|
||||||
|
|
||||||
|
deleteCase("fixed-width bucket wildcard", `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:DeleteBucket","Resource":"arn:aws:s3:::BUCKET_WILDCARD"}]
|
||||||
|
}`, false)
|
||||||
|
|
||||||
|
deleteCase("NotResource exclusion", `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[{"Effect":"Allow","Action":"s3:*","NotResource":"arn:aws:s3:::BUCKET/*"}]
|
||||||
|
}`, false)
|
||||||
|
|
||||||
|
deleteCase("Deny coverage", `{
|
||||||
|
"Version":"2012-10-17",
|
||||||
|
"Statement":[
|
||||||
|
{"Effect":"Allow","Action":"s3:*","Resource":"*"},
|
||||||
|
{"Effect":"Deny","Action":"s3:DeleteBucket","Resource":"arn:aws:s3:::BUCKET/*"}
|
||||||
|
]
|
||||||
|
}`, false)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -9,10 +9,11 @@ replace github.com/minio/console => github.com/pgsty/silo-console v0.0.0-2026080
|
|||||||
// Use Pigsty's maintained mc fork for Console's embedded client code.
|
// Use Pigsty's maintained mc fork for Console's embedded client code.
|
||||||
replace github.com/minio/mc => github.com/pgsty/mc v0.0.0-20260801042411-ad10a2a10b76
|
replace github.com/minio/mc => github.com/pgsty/mc v0.0.0-20260801042411-ad10a2a10b76
|
||||||
|
|
||||||
// Fix LDAP TLS regression: DialURL() was not passing TLS config for ldaps:// connections,
|
// Use Pigsty's maintained SILO package fork while preserving upstream import paths.
|
||||||
// causing InsecureSkipVerify, RootCAs, and other TLS settings to be silently ignored.
|
// This retains the LDAP TLS fix tracked in https://github.com/pgsty/minio/issues/15.
|
||||||
// See: https://github.com/pgsty/minio/issues/15
|
// v3.11.0 follows upstream minio/pkg's 3.11 line and carries the
|
||||||
replace github.com/minio/pkg/v3 => github.com/pgsty/minio-pkg/v3 v3.6.3
|
// minio/minio#20449 bucket-write boundary hardening.
|
||||||
|
replace github.com/minio/pkg/v3 => github.com/pgsty/silo-pkg/v3 v3.11.0
|
||||||
|
|
||||||
// v22.7.0 does not compile on NetBSD because its unix implementation uses
|
// v22.7.0 does not compile on NetBSD because its unix implementation uses
|
||||||
// CLOCK_MONOTONIC, which is unavailable there. Keep the last portable release
|
// CLOCK_MONOTONIC, which is unavailable there. Keep the last portable release
|
||||||
@@ -47,7 +48,7 @@ require (
|
|||||||
github.com/fatih/color v1.19.0
|
github.com/fatih/color v1.19.0
|
||||||
github.com/felixge/fgprof v0.9.5
|
github.com/felixge/fgprof v0.9.5
|
||||||
github.com/fraugster/parquet-go v0.12.0
|
github.com/fraugster/parquet-go v0.12.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.12
|
github.com/go-ldap/ldap/v3 v3.4.14
|
||||||
github.com/go-openapi/loads v0.23.3
|
github.com/go-openapi/loads v0.23.3
|
||||||
github.com/go-sql-driver/mysql v1.9.3
|
github.com/go-sql-driver/mysql v1.9.3
|
||||||
github.com/gobwas/ws v1.4.0
|
github.com/gobwas/ws v1.4.0
|
||||||
@@ -103,7 +104,7 @@ require (
|
|||||||
github.com/rs/cors v1.11.1
|
github.com/rs/cors v1.11.1
|
||||||
github.com/secure-io/sio-go v0.3.1
|
github.com/secure-io/sio-go v0.3.1
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5
|
github.com/shirou/gopsutil/v3 v3.24.5
|
||||||
github.com/tinylib/msgp v1.6.3
|
github.com/tinylib/msgp v1.6.4
|
||||||
github.com/valyala/bytebufferpool v1.0.0
|
github.com/valyala/bytebufferpool v1.0.0
|
||||||
github.com/xdg/scram v1.0.5
|
github.com/xdg/scram v1.0.5
|
||||||
github.com/zeebo/xxh3 v1.1.0
|
github.com/zeebo/xxh3 v1.1.0
|
||||||
@@ -111,7 +112,7 @@ require (
|
|||||||
go.etcd.io/etcd/client/v3 v3.6.9
|
go.etcd.io/etcd/client/v3 v3.6.9
|
||||||
go.uber.org/atomic v1.11.0
|
go.uber.org/atomic v1.11.0
|
||||||
go.uber.org/zap v1.28.0
|
go.uber.org/zap v1.28.0
|
||||||
go.yaml.in/yaml/v3 v3.0.4
|
go.yaml.in/yaml/v3 v3.0.5
|
||||||
goftp.io/server/v2 v2.0.2
|
goftp.io/server/v2 v2.0.2
|
||||||
golang.org/x/crypto v0.54.0
|
golang.org/x/crypto v0.54.0
|
||||||
golang.org/x/oauth2 v0.36.0
|
golang.org/x/oauth2 v0.36.0
|
||||||
@@ -169,7 +170,7 @@ require (
|
|||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
github.com/fatih/structs v1.1.0 // indirect
|
github.com/fatih/structs v1.1.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.8 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
|
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
@@ -184,7 +185,7 @@ require (
|
|||||||
github.com/go-openapi/strfmt v0.26.2 // indirect
|
github.com/go-openapi/strfmt v0.26.2 // indirect
|
||||||
github.com/go-openapi/swag v0.25.5 // indirect
|
github.com/go-openapi/swag v0.25.5 // indirect
|
||||||
github.com/go-openapi/swag/cmdutils v0.25.5 // indirect
|
github.com/go-openapi/swag/cmdutils v0.25.5 // indirect
|
||||||
github.com/go-openapi/swag/conv v0.25.5 // indirect
|
github.com/go-openapi/swag/conv v0.28.0 // indirect
|
||||||
github.com/go-openapi/swag/fileutils v0.25.5 // indirect
|
github.com/go-openapi/swag/fileutils v0.25.5 // indirect
|
||||||
github.com/go-openapi/swag/jsonname v0.26.0 // indirect
|
github.com/go-openapi/swag/jsonname v0.26.0 // indirect
|
||||||
github.com/go-openapi/swag/jsonutils v0.25.5 // indirect
|
github.com/go-openapi/swag/jsonutils v0.25.5 // indirect
|
||||||
@@ -192,7 +193,7 @@ require (
|
|||||||
github.com/go-openapi/swag/mangling v0.25.5 // indirect
|
github.com/go-openapi/swag/mangling v0.25.5 // indirect
|
||||||
github.com/go-openapi/swag/netutils v0.25.5 // indirect
|
github.com/go-openapi/swag/netutils v0.25.5 // indirect
|
||||||
github.com/go-openapi/swag/stringutils v0.25.5 // indirect
|
github.com/go-openapi/swag/stringutils v0.25.5 // indirect
|
||||||
github.com/go-openapi/swag/typeutils v0.25.5 // indirect
|
github.com/go-openapi/swag/typeutils v0.28.0 // indirect
|
||||||
github.com/go-openapi/swag/yamlutils v0.25.5 // indirect
|
github.com/go-openapi/swag/yamlutils v0.25.5 // indirect
|
||||||
github.com/go-openapi/validate v0.25.2 // indirect
|
github.com/go-openapi/validate v0.25.2 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||||
@@ -238,9 +239,9 @@ require (
|
|||||||
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
|
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88 // indirect
|
github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||||
github.com/mattn/go-ieproxy v0.0.12 // indirect
|
github.com/mattn/go-ieproxy v0.0.12 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.24 // indirect
|
||||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.21 // indirect
|
github.com/mattn/go-runewidth v0.0.21 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
|
|||||||
@@ -184,14 +184,14 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu
|
|||||||
github.com/fraugster/parquet-go v0.12.0 h1:1slnC5y2VWEOUSlzbeXatM0BvSWcLUDsR/EcZsXXCZc=
|
github.com/fraugster/parquet-go v0.12.0 h1:1slnC5y2VWEOUSlzbeXatM0BvSWcLUDsR/EcZsXXCZc=
|
||||||
github.com/fraugster/parquet-go v0.12.0/go.mod h1:dGzUxdNqXsAijatByVgbAWVPlFirnhknQbdazcUIjY0=
|
github.com/fraugster/parquet-go v0.12.0/go.mod h1:dGzUxdNqXsAijatByVgbAWVPlFirnhknQbdazcUIjY0=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
github.com/go-asn1-ber/asn1-ber v1.5.8 h1:H9AZkK22UOmfX8J84ubyaZxKJZ3FMHVwn8swoMML7iQ=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.5.8/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
|
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4=
|
github.com/go-ldap/ldap/v3 v3.4.14 h1:D6PYdEgsaVzsXyr6w/yDC06Ria4uUhWm+Rb+er8lfAs=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo=
|
github.com/go-ldap/ldap/v3 v3.4.14/go.mod h1:S4eJUMUNjDkE0ZJtIZdybwyb03sGGLW6gxXT1Hs8VKA=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
@@ -220,8 +220,8 @@ github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+T
|
|||||||
github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA=
|
github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA=
|
||||||
github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c=
|
github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c=
|
||||||
github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
|
github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
|
||||||
github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g=
|
github.com/go-openapi/swag/conv v0.28.0 h1:GtqqbyFe7vR5Y7ehxG9W6/OvrSFdf1OLeTGp40TqxH8=
|
||||||
github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k=
|
github.com/go-openapi/swag/conv v0.28.0/go.mod h1:mbUE+mzctnhxi864m0Q07SpN8OowD9JhxmxuYvZZD/k=
|
||||||
github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk=
|
github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk=
|
||||||
github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc=
|
github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc=
|
||||||
github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w=
|
github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w=
|
||||||
@@ -238,14 +238,14 @@ github.com/go-openapi/swag/netutils v0.25.5 h1:LZq2Xc2QI8+7838elRAaPCeqJnHODfSyO
|
|||||||
github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14=
|
github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14=
|
||||||
github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M=
|
github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M=
|
||||||
github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII=
|
github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII=
|
||||||
github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E=
|
github.com/go-openapi/swag/typeutils v0.28.0 h1:nRBKSBXjDgf01VDPB3fWeD9nQuhCOVeIYAkUx2tbkyY=
|
||||||
github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc=
|
github.com/go-openapi/swag/typeutils v0.28.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
|
||||||
github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ=
|
github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ=
|
||||||
github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ=
|
github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ=
|
||||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.1 h1:NZOrZmIb6PTv5LTFxr5/mKV/FjbUzGE7E6gLz7vFoOQ=
|
github.com/go-openapi/testify/enable/yaml/v2 v2.4.1 h1:NZOrZmIb6PTv5LTFxr5/mKV/FjbUzGE7E6gLz7vFoOQ=
|
||||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.1/go.mod h1:r7dwsujEHawapMsxA69i+XMGZrQ5tRauhLAjV/sxg3Q=
|
github.com/go-openapi/testify/enable/yaml/v2 v2.4.1/go.mod h1:r7dwsujEHawapMsxA69i+XMGZrQ5tRauhLAjV/sxg3Q=
|
||||||
github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4=
|
github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug=
|
||||||
github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
||||||
github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0=
|
github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0=
|
||||||
github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY=
|
github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
@@ -431,15 +431,15 @@ github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88/go.mod h1:autxFIv
|
|||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
|
||||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
github.com/mattn/go-ieproxy v0.0.12 h1:OZkUFJC3ESNZPQ+6LzC3VJIFSnreeFLQyqvBWtvfL2M=
|
github.com/mattn/go-ieproxy v0.0.12 h1:OZkUFJC3ESNZPQ+6LzC3VJIFSnreeFLQyqvBWtvfL2M=
|
||||||
github.com/mattn/go-ieproxy v0.0.12/go.mod h1:Vn+N61199DAnVeTgaF8eoB9PvLO8P3OBnG95ENh7B7c=
|
github.com/mattn/go-ieproxy v0.0.12/go.mod h1:Vn+N61199DAnVeTgaF8eoB9PvLO8P3OBnG95ENh7B7c=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
||||||
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
@@ -549,10 +549,10 @@ github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwp
|
|||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pgsty/mc v0.0.0-20260801042411-ad10a2a10b76 h1:UIlUuz0LQKw4QlAljhv7nPDDFC1+n+e0iED7rWZrgZ8=
|
github.com/pgsty/mc v0.0.0-20260801042411-ad10a2a10b76 h1:UIlUuz0LQKw4QlAljhv7nPDDFC1+n+e0iED7rWZrgZ8=
|
||||||
github.com/pgsty/mc v0.0.0-20260801042411-ad10a2a10b76/go.mod h1:cTbS+9jGR4Qs7xTf5DEhmCTbzcDWrKMs8ZmTUnCU49E=
|
github.com/pgsty/mc v0.0.0-20260801042411-ad10a2a10b76/go.mod h1:cTbS+9jGR4Qs7xTf5DEhmCTbzcDWrKMs8ZmTUnCU49E=
|
||||||
github.com/pgsty/minio-pkg/v3 v3.6.3 h1:lskojLFaoMfn9dWTgfRAd0n3RdQ/J+XsCKr77UlBl4g=
|
|
||||||
github.com/pgsty/minio-pkg/v3 v3.6.3/go.mod h1:Uyp31bhmWTpGpBiVir0wgouN9iUYipSm4nYc/veAgjI=
|
|
||||||
github.com/pgsty/silo-console v0.0.0-20260804042150-b952a1202869 h1:HLfc2ZdAycnI/bLl+TdsuckyzSWrwQarK38pS14yH/Q=
|
github.com/pgsty/silo-console v0.0.0-20260804042150-b952a1202869 h1:HLfc2ZdAycnI/bLl+TdsuckyzSWrwQarK38pS14yH/Q=
|
||||||
github.com/pgsty/silo-console v0.0.0-20260804042150-b952a1202869/go.mod h1:7J8wCQsNT5S7GqCHnQqgj0T7Nagp1fklJhfBJI+v0XI=
|
github.com/pgsty/silo-console v0.0.0-20260804042150-b952a1202869/go.mod h1:7J8wCQsNT5S7GqCHnQqgj0T7Nagp1fklJhfBJI+v0XI=
|
||||||
|
github.com/pgsty/silo-pkg/v3 v3.11.0 h1:wjN5d+tWD8Twq+e7k/KBBVhnWXC8xTIlfTcnGIKkmjc=
|
||||||
|
github.com/pgsty/silo-pkg/v3 v3.11.0/go.mod h1:E2AB4oOgfDeb9In1KDBTrn9wzfvr0WzoPkbXW7wbwBQ=
|
||||||
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
|
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
|
||||||
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
||||||
github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
|
github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
|
||||||
@@ -654,8 +654,8 @@ github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT
|
|||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tinylib/msgp v1.6.3 h1:bCSxiTz386UTgyT1i0MSCvdbWjVW+8sG3PjkGsZQt4s=
|
github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ=
|
||||||
github.com/tinylib/msgp v1.6.3/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
|
github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
|
||||||
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
||||||
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
||||||
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
||||||
@@ -726,8 +726,8 @@ go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo=
|
|||||||
go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q=
|
go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q=
|
||||||
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||||
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
||||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||||
goftp.io/server/v2 v2.0.2 h1:tkZpqyXys+vC15W5yGMi8Kzmbv1QSgeKr8qJXBnJbm8=
|
goftp.io/server/v2 v2.0.2 h1:tkZpqyXys+vC15W5yGMi8Kzmbv1QSgeKr8qJXBnJbm8=
|
||||||
goftp.io/server/v2 v2.0.2/go.mod h1:Fl1WdcV7fx1pjOWx7jEHb7tsJ8VwE7+xHu6bVJ6r2qg=
|
goftp.io/server/v2 v2.0.2/go.mod h1:Fl1WdcV7fx1pjOWx7jEHb7tsJ8VwE7+xHu6bVJ6r2qg=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
|||||||
Reference in New Issue
Block a user