@ -26,6 +26,7 @@ import (
"io/ioutil"
"io/ioutil"
"math/rand"
"math/rand"
"net/http"
"net/http"
"net/http/cookiejar"
"net/http/httputil"
"net/http/httputil"
"net/url"
"net/url"
"os"
"os"
@ -34,18 +35,21 @@ import (
"strings"
"strings"
"time"
"time"
"github.com/minio/minio-go/v6/pkg/credentials"
"github.com/minio/minio-go/v6/pkg/s3signer"
"github.com/minio/minio-go/v6/pkg/s3signer"
"github.com/minio/minio-go/v6/pkg/s3utils"
"github.com/minio/minio-go/v6/pkg/s3utils"
"golang.org/x/net/publicsuffix"
)
)
// AdminClient implements Amazon S3 compatible methods.
// AdminClient implements Amazon S3 compatible methods.
type AdminClient struct {
type AdminClient struct {
/// Standard options.
/// Standard options.
// AccessKeyID required for authorized requests.
// Parsed endpoint url provided by the user.
accessKeyID string
endpointURL * url . URL
// SecretAccessKey required for authorized requests.
secretAccessKey string
// Holds various credential providers.
credsProvider * credentials . Credentials
// User supplied.
// User supplied.
appInfo struct {
appInfo struct {
@ -53,8 +57,6 @@ type AdminClient struct {
appVersion string
appVersion string
}
}
endpointURL url . URL
// Indicate whether we are using https or not
// Indicate whether we are using https or not
secure bool
secure bool
@ -85,38 +87,67 @@ const (
libraryUserAgent = libraryUserAgentPrefix + libraryName + "/" + libraryVersion
libraryUserAgent = libraryUserAgentPrefix + libraryName + "/" + libraryVersion
)
)
// New - instantiate minio client Client, adds automatic verification of signature.
// Options for New method
type Options struct {
Creds * credentials . Credentials
Secure bool
// Add future fields here
}
// New - instantiate minio admin client
func New ( endpoint string , accessKeyID , secretAccessKey string , secure bool ) ( * AdminClient , error ) {
func New ( endpoint string , accessKeyID , secretAccessKey string , secure bool ) ( * AdminClient , error ) {
clnt , err := privateNew ( endpoint , accessKeyID , secretAccessKey , secure )
creds := credentials . NewStaticV4 ( accessKeyID , secretAccessKey , "" )
clnt , err := privateNew ( endpoint , creds , secure )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
return clnt , nil
return clnt , nil
}
}
func privateNew ( endpoint , accessKeyID , secretAccessKey string , secure bool ) ( * AdminClient , error ) {
// NewWithOptions - instantiate minio admin client with options.
func NewWithOptions ( endpoint string , opts * Options ) ( * AdminClient , error ) {
clnt , err := privateNew ( endpoint , opts . Creds , opts . Secure )
if err != nil {
return nil , err
}
return clnt , nil
}
func privateNew ( endpoint string , creds * credentials . Credentials , secure bool ) ( * AdminClient , error ) {
// Initialize cookies to preserve server sent cookies if any and replay
// them upon each request.
jar , err := cookiejar . New ( & cookiejar . Options { PublicSuffixList : publicsuffix . List } )
if err != nil {
return nil , err
}
// construct endpoint.
// construct endpoint.
endpointURL , err := getEndpointURL ( endpoint , secure )
endpointURL , err := getEndpointURL ( endpoint , secure )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
// instantiate new Client.
clnt := new ( AdminClient )
clnt := & AdminClient {
accessKeyID : accessKeyID ,
// Save the credentials.
secretAccessKey : secretAccessKey ,
clnt . credsProvider = creds
// Remember whether we are using https or not
secure : secure ,
// Remember whether we are using https or not
// Save endpoint URL, user agent for future uses.
clnt . secure = secure
endpointURL : * endpointURL ,
// Instantiate http client and bucket location cache.
// Save endpoint URL, user agent for future uses.
httpClient : & http . Client {
clnt . endpointURL = endpointURL
Transport : DefaultTransport ( secure ) ,
} ,
// Instantiate http client and bucket location cache.
// Introduce a new locked random seed.
clnt . httpClient = & http . Client {
random : rand . New ( & lockedRandSource { src : rand . NewSource ( time . Now ( ) . UTC ( ) . UnixNano ( ) ) } ) ,
Jar : jar ,
Transport : DefaultTransport ( secure ) ,
}
}
// Add locked pseudo-random number generator.
clnt . random = rand . New ( & lockedRandSource { src : rand . NewSource ( time . Now ( ) . UTC ( ) . UnixNano ( ) ) } )
// Return.
// Return.
return clnt , nil
return clnt , nil
}
}
@ -393,6 +424,16 @@ func (adm AdminClient) setUserAgent(req *http.Request) {
}
}
}
}
func ( adm AdminClient ) getSecretKey ( ) string {
value , err := adm . credsProvider . Get ( )
if err != nil {
// Return empty, call will fail.
return ""
}
return value . SecretAccessKey
}
// newRequest - instantiate a new HTTP request for a given method.
// newRequest - instantiate a new HTTP request for a given method.
func ( adm AdminClient ) newRequest ( method string , reqData requestData ) ( req * http . Request , err error ) {
func ( adm AdminClient ) newRequest ( method string , reqData requestData ) ( req * http . Request , err error ) {
// If no method is supplied default to 'POST'.
// If no method is supplied default to 'POST'.
@ -415,6 +456,17 @@ func (adm AdminClient) newRequest(method string, reqData requestData) (req *http
return nil , err
return nil , err
}
}
value , err := adm . credsProvider . Get ( )
if err != nil {
return nil , err
}
var (
accessKeyID = value . AccessKeyID
secretAccessKey = value . SecretAccessKey
sessionToken = value . SessionToken
)
adm . setUserAgent ( req )
adm . setUserAgent ( req )
for k , v := range reqData . customHeaders {
for k , v := range reqData . customHeaders {
req . Header . Set ( k , v [ 0 ] )
req . Header . Set ( k , v [ 0 ] )
@ -425,7 +477,7 @@ func (adm AdminClient) newRequest(method string, reqData requestData) (req *http
req . Header . Set ( "X-Amz-Content-Sha256" , hex . EncodeToString ( sum256 ( reqData . content ) ) )
req . Header . Set ( "X-Amz-Content-Sha256" , hex . EncodeToString ( sum256 ( reqData . content ) ) )
req . Body = ioutil . NopCloser ( bytes . NewReader ( reqData . content ) )
req . Body = ioutil . NopCloser ( bytes . NewReader ( reqData . content ) )
req = s3signer . SignV4 ( * req , adm . a ccessKeyID , adm . secretAccessKey , "" , location )
req = s3signer . SignV4 ( * req , accessKeyID , secretAccessKey , sessionToken , location )
return req , nil
return req , nil
}
}