diff --git a/.gitignore b/.gitignore
index b9482596bf..3df0c18a67 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,7 @@ dist/
# Ignore tls cert and key
private.key
public.crt
+
+# Ignore VsCode files
+.vscode/
+*.code-workspace
diff --git a/go.mod b/go.mod
index 6ae57105f6..bbe55d228d 100644
--- a/go.mod
+++ b/go.mod
@@ -16,7 +16,7 @@ require (
github.com/json-iterator/go v1.1.9
github.com/minio/cli v1.22.0
github.com/minio/mc v0.0.0-20200415193718-68b638f2f96c
- github.com/minio/minio v0.0.0-20200427162205-eff4127efd63
+ github.com/minio/minio v0.0.0-20200428222040-c3c3e9087bc1
github.com/minio/minio-go/v6 v6.0.55-0.20200424204115-7506d2996b22
github.com/satori/go.uuid v1.2.0
github.com/stretchr/testify v1.5.1
diff --git a/go.sum b/go.sum
index 4055a8f09a..efa3d33dcb 100644
--- a/go.sum
+++ b/go.sum
@@ -2,6 +2,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.39.0 h1:UgQP9na6OTfp4dsAiz/eFpFA1C6tPdH5wiRdi19tuMw=
cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts=
+contrib.go.opencensus.io/exporter/ocagent v0.5.0 h1:TKXjQSRS0/cCDrP7KvkgU6SmILtF/yV2TOs/02K/WZQ=
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
git.apache.org/thrift.git v0.13.0 h1:/3bz5WZ+sqYArk7MBBBbDufMxKKOA56/6JO6psDpUDY=
git.apache.org/thrift.git v0.13.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
@@ -9,6 +10,7 @@ github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZ
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
github.com/Azure/azure-storage-blob-go v0.8.0 h1:53qhf0Oxa0nOjgbDeeYPUeyiNmafAFEY95rZLK0Tj6o=
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
+github.com/Azure/go-autorest v11.7.1+incompatible h1:M2YZIajBBVekV86x0rr1443Lc1F/Ylxb9w+5EtSyX3Q=
github.com/Azure/go-autorest v11.7.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
@@ -19,6 +21,7 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/sarama v1.24.1 h1:svn9vfN3R1Hz21WR2Gj0VW9ehaDGkiOS+VqlIcZOkMI=
github.com/Shopify/sarama v1.24.1/go.mod h1:fGP8eQ6PugKEI0iUETYYtnP6d1pH/bdDMTel1X5ajsU=
+github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
@@ -31,6 +34,7 @@ github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 h1:nWDRPC
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM=
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
@@ -47,6 +51,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLM
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
+github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -97,8 +102,10 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
+github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.4.1/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ=
+github.com/frankban/quicktest v1.7.2 h1:2QxQoC1TS09S7fhCPsrvqYdvP1H5M1P1ih5ABm3BTYk=
github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
@@ -264,8 +271,11 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
+github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
+github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
@@ -286,6 +296,7 @@ github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/raft v1.1.1-0.20190703171940-f639636d18e0 h1:msEDtkZC3STZq6Pthlju+jKruuNHXCZAWhghDK47HcM=
github.com/hashicorp/raft v1.1.1-0.20190703171940-f639636d18e0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk=
github.com/hashicorp/vault/api v1.0.4 h1:j08Or/wryXT4AcHj1oCbMd7IijXcKzYUGw59LGu9onU=
@@ -388,18 +399,10 @@ github.com/minio/mc v0.0.0-20200415193718-68b638f2f96c h1:JLr0fYpCleodj9nGB5hfsJ
github.com/minio/mc v0.0.0-20200415193718-68b638f2f96c/go.mod h1:l9PuOY62zT7AQJqopDjfo/T22AIBJSb2yXPVZf4RlhM=
github.com/minio/minio v0.0.0-20200415191640-bde0f444dbab h1:9hlqghJl3e3HorXa6ADWsz6ECq790t4iQs07VD9JctM=
github.com/minio/minio v0.0.0-20200415191640-bde0f444dbab/go.mod h1:v8oQPMMaTkjDwp5cOz1WCElA4Ik+X+0y4On+VMk0fis=
-github.com/minio/minio v0.0.0-20200421050159-282c9f790a03 h1:qEWJAXNbLp1Uovs9gzPQ8gWGFY8X+58WcttySAMgny0=
-github.com/minio/minio v0.0.0-20200421050159-282c9f790a03/go.mod h1:zBua5AiljGs1Irdl2XEyiJjvZVCVDIG8gjozzRBcVlw=
-github.com/minio/minio v0.0.0-20200422230658-6817c5ea58fb h1:qDqH+rGTsORP1Y7M8JSswlWPl5L35C9fuz9VR2qhe8Y=
-github.com/minio/minio v0.0.0-20200422230658-6817c5ea58fb/go.mod h1:zBua5AiljGs1Irdl2XEyiJjvZVCVDIG8gjozzRBcVlw=
-github.com/minio/minio v0.0.0-20200424205148-45e22cf8aa2a h1:KKMhJEuVCtfrDDtrG5BT5pp37ZjqGSUEX/yOlJLrhD4=
-github.com/minio/minio v0.0.0-20200424205148-45e22cf8aa2a/go.mod h1:zBua5AiljGs1Irdl2XEyiJjvZVCVDIG8gjozzRBcVlw=
-github.com/minio/minio v0.0.0-20200427162205-eff4127efd63 h1:hLWy7ugfhRfyPoIiflLe7lKnKy8O61LUX1G8rSJXZLQ=
-github.com/minio/minio v0.0.0-20200427162205-eff4127efd63/go.mod h1:7Zkko5V0gucT+jh6wDhao6n78MZ6exxHSawsH897VaA=
+github.com/minio/minio v0.0.0-20200428222040-c3c3e9087bc1 h1:DQjH/653WCerOeZCp3BxAgkmRiQybHYiprbTFs+brgA=
+github.com/minio/minio v0.0.0-20200428222040-c3c3e9087bc1/go.mod h1:HxnN5FYGIii8ZH6d+LH5UNOSSIonbJkYPqP6gWelVO0=
github.com/minio/minio-go/v6 v6.0.53 h1:8jzpwiOzZ5Iz7/goFWqNZRICbyWYShbb5rARjrnSCNI=
github.com/minio/minio-go/v6 v6.0.53/go.mod h1:DIvC/IApeHX8q1BAMVCXSXwpmrmM+I+iBvhvztQorfI=
-github.com/minio/minio-go/v6 v6.0.54 h1:3bUIEVa5hkVqY7vTGY8yfO53qP5CiSddM8OOPSU0JxQ=
-github.com/minio/minio-go/v6 v6.0.54/go.mod h1:DIvC/IApeHX8q1BAMVCXSXwpmrmM+I+iBvhvztQorfI=
github.com/minio/minio-go/v6 v6.0.55-0.20200424204115-7506d2996b22 h1:nZEve4vdUhwHBoV18zRvPDgjL6NYyDJE5QJvz3l9bRs=
github.com/minio/minio-go/v6 v6.0.55-0.20200424204115-7506d2996b22/go.mod h1:KQMM+/44DSlSGSQWSfRrAZ12FVMmpWNuX37i2AX0jfI=
github.com/minio/parquet-go v0.0.0-20200414234858-838cfa8aae61 h1:pUSI/WKPdd77gcuoJkSzhJ4wdS8OMDOsOu99MtpXEQA=
@@ -432,14 +435,20 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ
github.com/montanaflynn/stats v0.5.0 h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk=
github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nats-io/gnatsd v1.4.1 h1:RconcfDeWpKCD6QIIwiVFcvForlXpWeJP7i5/lDLy44=
github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ=
+github.com/nats-io/go-nats v1.7.2 h1:cJujlwCYR8iMz5ofZSD/p2WLW8FabhkQ2lIEVbSvNSA=
github.com/nats-io/go-nats v1.7.2/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0=
+github.com/nats-io/go-nats-streaming v0.4.4 h1:1I3lkZDRdQYXb+holjdqZ2J6xyekrD06o9Fd8rWlgP4=
github.com/nats-io/go-nats-streaming v0.4.4/go.mod h1:gfq4R3c9sKAINOpelo0gn/b9QDMBZnmrttcsNF+lqyo=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
+github.com/nats-io/nats-server v1.4.1 h1:Ul1oSOGNV/L8kjr4v6l2f9Yet6WY+LevH1/7cRZ/qyA=
github.com/nats-io/nats-server v1.4.1/go.mod h1:c8f/fHd2B6Hgms3LtCaI7y6pC4WD1f4SUxcCud5vhBc=
+github.com/nats-io/nats-server/v2 v2.1.2 h1:i2Ly0B+1+rzNZHHWtD4ZwKi+OU5l+uQo1iDHZ2PmiIc=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
+github.com/nats-io/nats-streaming-server v0.14.2 h1:WjQMDqVOwsI0Nb0E+XmEs1LY17CwHRbTCSTWKhw9fXs=
github.com/nats-io/nats-streaming-server v0.14.2/go.mod h1:RyqtDJZvMZO66YmyjIYdIvS69zu/wDAkyNWa8PIUa5c=
github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
@@ -456,6 +465,7 @@ github.com/nsqio/go-nsq v1.0.7 h1:O0pIZJYTf+x7cZBA0UMY8WxFG79lYTURmWzAAh48ljY=
github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/getopt v0.0.0-20180729010549-6fdd0a2c7117/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
@@ -529,6 +539,8 @@ github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRNFYlvKwSr5zff2v+uPHaffZ6/M4k=
@@ -565,6 +577,10 @@ github.com/unrolled/secure v1.0.7/go.mod h1:uGc1OcRF8gCVBA+ANksKmvM85Hka6SZtQIbr
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
+github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
+github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
+github.com/willf/bloom v2.0.3+incompatible h1:QDacWdqcAUI1MPOwIQZRy9kOR7yxfyEmxX8Wdm2/JPA=
+github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
@@ -639,6 +655,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/models/service_account.go b/models/service_account.go
new file mode 100644
index 0000000000..25ef80c891
--- /dev/null
+++ b/models/service_account.go
@@ -0,0 +1,60 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// 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 .
+//
+
+package models
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag"
+)
+
+// ServiceAccount service account
+//
+// swagger:model serviceAccount
+type ServiceAccount struct {
+
+ // policy to be applied to the Service Account if any
+ Policy string `json:"policy,omitempty"`
+}
+
+// Validate validates this service account
+func (m *ServiceAccount) Validate(formats strfmt.Registry) error {
+ return nil
+}
+
+// MarshalBinary interface implementation
+func (m *ServiceAccount) MarshalBinary() ([]byte, error) {
+ if m == nil {
+ return nil, nil
+ }
+ return swag.WriteJSON(m)
+}
+
+// UnmarshalBinary interface implementation
+func (m *ServiceAccount) UnmarshalBinary(b []byte) error {
+ var res ServiceAccount
+ if err := swag.ReadJSON(b, &res); err != nil {
+ return err
+ }
+ *m = res
+ return nil
+}
diff --git a/models/service_account_creds.go b/models/service_account_creds.go
new file mode 100644
index 0000000000..43bbf1a2bc
--- /dev/null
+++ b/models/service_account_creds.go
@@ -0,0 +1,63 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// 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 .
+//
+
+package models
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag"
+)
+
+// ServiceAccountCreds service account creds
+//
+// swagger:model serviceAccountCreds
+type ServiceAccountCreds struct {
+
+ // access key
+ AccessKey string `json:"accessKey,omitempty"`
+
+ // secret key
+ SecretKey string `json:"secretKey,omitempty"`
+}
+
+// Validate validates this service account creds
+func (m *ServiceAccountCreds) Validate(formats strfmt.Registry) error {
+ return nil
+}
+
+// MarshalBinary interface implementation
+func (m *ServiceAccountCreds) MarshalBinary() ([]byte, error) {
+ if m == nil {
+ return nil, nil
+ }
+ return swag.WriteJSON(m)
+}
+
+// UnmarshalBinary interface implementation
+func (m *ServiceAccountCreds) UnmarshalBinary(b []byte) error {
+ var res ServiceAccountCreds
+ if err := swag.ReadJSON(b, &res); err != nil {
+ return err
+ }
+ *m = res
+ return nil
+}
diff --git a/pkg/auth/jwt.go b/pkg/auth/jwt.go
index 7d8520b2f2..93b9e058cd 100644
--- a/pkg/auth/jwt.go
+++ b/pkg/auth/jwt.go
@@ -52,6 +52,7 @@ func IsJWTValid(token string) bool {
return err == nil
}
+// DecryptedClaims claims struct for decrypted credentials
type DecryptedClaims struct {
AccessKeyID string
SecretAccessKey string
diff --git a/restapi/admin_notification_endpoints.go b/restapi/admin_notification_endpoints.go
index 6829341298..bdbed9d332 100644
--- a/restapi/admin_notification_endpoints.go
+++ b/restapi/admin_notification_endpoints.go
@@ -141,7 +141,6 @@ func addNotificationEndpoint(ctx context.Context, client MinioAdmin, params *adm
err := setConfigWithARNAccountID(ctx, client, &configName, configs, *params.Body.AccountID)
if err != nil {
- log.Println(err)
return nil, err
}
diff --git a/restapi/client-admin.go b/restapi/client-admin.go
index 017836fa3d..af8fffd78e 100644
--- a/restapi/client-admin.go
+++ b/restapi/client-admin.go
@@ -26,6 +26,7 @@ import (
"github.com/minio/mc/pkg/probe"
"github.com/minio/mcs/pkg/auth"
"github.com/minio/minio-go/v6/pkg/credentials"
+ mauth "github.com/minio/minio/pkg/auth"
iampolicy "github.com/minio/minio/pkg/iam/policy"
"github.com/minio/minio/pkg/madmin"
)
@@ -79,6 +80,8 @@ type MinioAdmin interface {
serverInfo(ctx context.Context) (madmin.InfoMessage, error)
startProfiling(ctx context.Context, profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error)
stopProfiling(ctx context.Context) (io.ReadCloser, error)
+ // Service Accounts
+ addServiceAccount(ctx context.Context, policy *iampolicy.Policy) (mauth.Credentials, error)
}
// Interface implementation
@@ -194,6 +197,11 @@ func (ac adminClient) stopProfiling(ctx context.Context) (io.ReadCloser, error)
return ac.client.DownloadProfilingData(ctx)
}
+// implements madmin.AddServiceAccount()
+func (ac adminClient) addServiceAccount(ctx context.Context, policy *iampolicy.Policy) (mauth.Credentials, error) {
+ return ac.client.AddServiceAccount(ctx, policy)
+}
+
func newMAdminClient(jwt string) (*madmin.AdminClient, error) {
claims, err := auth.JWTAuthenticate(jwt)
if err != nil {
diff --git a/restapi/configure_mcs.go b/restapi/configure_mcs.go
index 509b988b4c..7276dd11ce 100644
--- a/restapi/configure_mcs.go
+++ b/restapi/configure_mcs.go
@@ -95,6 +95,8 @@ func configureAPI(api *operations.McsAPI) http.Handler {
registerAdminArnsHandlers(api)
// Register admin notification endpoints handlers
registerAdminNotificationEndpointsHandlers(api)
+ // Register admin Service Account Handlers
+ registerServiceAccountsHandlers(api)
api.PreServerShutdown = func() {}
diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go
index 8d7c13a29f..f7e9e14348 100644
--- a/restapi/embedded_spec.go
+++ b/restapi/embedded_spec.go
@@ -957,6 +957,39 @@ func init() {
}
}
},
+ "/service-accounts": {
+ "post": {
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "Create Service Account",
+ "operationId": "CreateServiceAccount",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/serviceAccount"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/serviceAccountCreds"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/service/restart": {
"post": {
"tags": [
@@ -1800,6 +1833,26 @@ func init() {
}
}
},
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "policy": {
+ "type": "string",
+ "title": "policy to be applied to the Service Account if any"
+ }
+ }
+ },
+ "serviceAccountCreds": {
+ "type": "object",
+ "properties": {
+ "accessKey": {
+ "type": "string"
+ },
+ "secretKey": {
+ "type": "string"
+ }
+ }
+ },
"sessionResponse": {
"type": "object",
"properties": {
@@ -2894,6 +2947,39 @@ func init() {
}
}
},
+ "/service-accounts": {
+ "post": {
+ "tags": [
+ "UserAPI"
+ ],
+ "summary": "Create Service Account",
+ "operationId": "CreateServiceAccount",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/serviceAccount"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/serviceAccountCreds"
+ }
+ },
+ "default": {
+ "description": "Generic error response.",
+ "schema": {
+ "$ref": "#/definitions/error"
+ }
+ }
+ }
+ }
+ },
"/service/restart": {
"post": {
"tags": [
@@ -3737,6 +3823,26 @@ func init() {
}
}
},
+ "serviceAccount": {
+ "type": "object",
+ "properties": {
+ "policy": {
+ "type": "string",
+ "title": "policy to be applied to the Service Account if any"
+ }
+ }
+ },
+ "serviceAccountCreds": {
+ "type": "object",
+ "properties": {
+ "accessKey": {
+ "type": "string"
+ },
+ "secretKey": {
+ "type": "string"
+ }
+ }
+ },
"sessionResponse": {
"type": "object",
"properties": {
diff --git a/restapi/operations/mcs_api.go b/restapi/operations/mcs_api.go
index 8e357ce180..ba8205e19f 100644
--- a/restapi/operations/mcs_api.go
+++ b/restapi/operations/mcs_api.go
@@ -96,6 +96,9 @@ func NewMcsAPI(spec *loads.Document) *McsAPI {
UserAPICreateBucketEventHandler: user_api.CreateBucketEventHandlerFunc(func(params user_api.CreateBucketEventParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.CreateBucketEvent has not yet been implemented")
}),
+ UserAPICreateServiceAccountHandler: user_api.CreateServiceAccountHandlerFunc(func(params user_api.CreateServiceAccountParams, principal *models.Principal) middleware.Responder {
+ return middleware.NotImplemented("operation user_api.CreateServiceAccount has not yet been implemented")
+ }),
UserAPIDeleteBucketHandler: user_api.DeleteBucketHandlerFunc(func(params user_api.DeleteBucketParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation user_api.DeleteBucket has not yet been implemented")
}),
@@ -251,6 +254,8 @@ type McsAPI struct {
AdminAPIConfigInfoHandler admin_api.ConfigInfoHandler
// UserAPICreateBucketEventHandler sets the operation handler for the create bucket event operation
UserAPICreateBucketEventHandler user_api.CreateBucketEventHandler
+ // UserAPICreateServiceAccountHandler sets the operation handler for the create service account operation
+ UserAPICreateServiceAccountHandler user_api.CreateServiceAccountHandler
// UserAPIDeleteBucketHandler sets the operation handler for the delete bucket operation
UserAPIDeleteBucketHandler user_api.DeleteBucketHandler
// UserAPIDeleteBucketEventHandler sets the operation handler for the delete bucket event operation
@@ -413,6 +418,9 @@ func (o *McsAPI) Validate() error {
if o.UserAPICreateBucketEventHandler == nil {
unregistered = append(unregistered, "user_api.CreateBucketEventHandler")
}
+ if o.UserAPICreateServiceAccountHandler == nil {
+ unregistered = append(unregistered, "user_api.CreateServiceAccountHandler")
+ }
if o.UserAPIDeleteBucketHandler == nil {
unregistered = append(unregistered, "user_api.DeleteBucketHandler")
}
@@ -641,6 +649,10 @@ func (o *McsAPI) initHandlerCache() {
o.handlers["POST"] = make(map[string]http.Handler)
}
o.handlers["POST"]["/buckets/{bucket_name}/events"] = user_api.NewCreateBucketEvent(o.context, o.UserAPICreateBucketEventHandler)
+ if o.handlers["POST"] == nil {
+ o.handlers["POST"] = make(map[string]http.Handler)
+ }
+ o.handlers["POST"]["/service-accounts"] = user_api.NewCreateServiceAccount(o.context, o.UserAPICreateServiceAccountHandler)
if o.handlers["DELETE"] == nil {
o.handlers["DELETE"] = make(map[string]http.Handler)
}
diff --git a/restapi/operations/user_api/create_service_account.go b/restapi/operations/user_api/create_service_account.go
new file mode 100644
index 0000000000..d5de45d68f
--- /dev/null
+++ b/restapi/operations/user_api/create_service_account.go
@@ -0,0 +1,90 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// 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 .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime/middleware"
+
+ "github.com/minio/mcs/models"
+)
+
+// CreateServiceAccountHandlerFunc turns a function with the right signature into a create service account handler
+type CreateServiceAccountHandlerFunc func(CreateServiceAccountParams, *models.Principal) middleware.Responder
+
+// Handle executing the request and returning a response
+func (fn CreateServiceAccountHandlerFunc) Handle(params CreateServiceAccountParams, principal *models.Principal) middleware.Responder {
+ return fn(params, principal)
+}
+
+// CreateServiceAccountHandler interface for that can handle valid create service account params
+type CreateServiceAccountHandler interface {
+ Handle(CreateServiceAccountParams, *models.Principal) middleware.Responder
+}
+
+// NewCreateServiceAccount creates a new http.Handler for the create service account operation
+func NewCreateServiceAccount(ctx *middleware.Context, handler CreateServiceAccountHandler) *CreateServiceAccount {
+ return &CreateServiceAccount{Context: ctx, Handler: handler}
+}
+
+/*CreateServiceAccount swagger:route POST /service-accounts UserAPI createServiceAccount
+
+Create Service Account
+
+*/
+type CreateServiceAccount struct {
+ Context *middleware.Context
+ Handler CreateServiceAccountHandler
+}
+
+func (o *CreateServiceAccount) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ route, rCtx, _ := o.Context.RouteInfo(r)
+ if rCtx != nil {
+ r = rCtx
+ }
+ var Params = NewCreateServiceAccountParams()
+
+ uprinc, aCtx, err := o.Context.Authorize(r, route)
+ if err != nil {
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+ if aCtx != nil {
+ r = aCtx
+ }
+ var principal *models.Principal
+ if uprinc != nil {
+ principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
+ }
+
+ if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
+ o.Context.Respond(rw, r, route.Produces, route, err)
+ return
+ }
+
+ res := o.Handler.Handle(Params, principal) // actually handle the request
+
+ o.Context.Respond(rw, r, route.Produces, route, res)
+
+}
diff --git a/restapi/operations/user_api/create_service_account_parameters.go b/restapi/operations/user_api/create_service_account_parameters.go
new file mode 100644
index 0000000000..d082bcb788
--- /dev/null
+++ b/restapi/operations/user_api/create_service_account_parameters.go
@@ -0,0 +1,94 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// 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 .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "io"
+ "net/http"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/runtime"
+ "github.com/go-openapi/runtime/middleware"
+
+ "github.com/minio/mcs/models"
+)
+
+// NewCreateServiceAccountParams creates a new CreateServiceAccountParams object
+// no default values defined in spec.
+func NewCreateServiceAccountParams() CreateServiceAccountParams {
+
+ return CreateServiceAccountParams{}
+}
+
+// CreateServiceAccountParams contains all the bound params for the create service account operation
+// typically these are obtained from a http.Request
+//
+// swagger:parameters CreateServiceAccount
+type CreateServiceAccountParams struct {
+
+ // HTTP Request Object
+ HTTPRequest *http.Request `json:"-"`
+
+ /*
+ Required: true
+ In: body
+ */
+ Body *models.ServiceAccount
+}
+
+// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
+// for simple values it will use straight method calls.
+//
+// To ensure default values, the struct must have been initialized with NewCreateServiceAccountParams() beforehand.
+func (o *CreateServiceAccountParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
+ var res []error
+
+ o.HTTPRequest = r
+
+ if runtime.HasBody(r) {
+ defer r.Body.Close()
+ var body models.ServiceAccount
+ if err := route.Consumer.Consume(r.Body, &body); err != nil {
+ if err == io.EOF {
+ res = append(res, errors.Required("body", "body"))
+ } else {
+ res = append(res, errors.NewParseError("body", "body", "", err))
+ }
+ } else {
+ // validate body object
+ if err := body.Validate(route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) == 0 {
+ o.Body = &body
+ }
+ }
+ } else {
+ res = append(res, errors.Required("body", "body"))
+ }
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
diff --git a/restapi/operations/user_api/create_service_account_responses.go b/restapi/operations/user_api/create_service_account_responses.go
new file mode 100644
index 0000000000..bd317f53a5
--- /dev/null
+++ b/restapi/operations/user_api/create_service_account_responses.go
@@ -0,0 +1,133 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// 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 .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "net/http"
+
+ "github.com/go-openapi/runtime"
+
+ "github.com/minio/mcs/models"
+)
+
+// CreateServiceAccountCreatedCode is the HTTP code returned for type CreateServiceAccountCreated
+const CreateServiceAccountCreatedCode int = 201
+
+/*CreateServiceAccountCreated A successful response.
+
+swagger:response createServiceAccountCreated
+*/
+type CreateServiceAccountCreated struct {
+
+ /*
+ In: Body
+ */
+ Payload *models.ServiceAccountCreds `json:"body,omitempty"`
+}
+
+// NewCreateServiceAccountCreated creates CreateServiceAccountCreated with default headers values
+func NewCreateServiceAccountCreated() *CreateServiceAccountCreated {
+
+ return &CreateServiceAccountCreated{}
+}
+
+// WithPayload adds the payload to the create service account created response
+func (o *CreateServiceAccountCreated) WithPayload(payload *models.ServiceAccountCreds) *CreateServiceAccountCreated {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the create service account created response
+func (o *CreateServiceAccountCreated) SetPayload(payload *models.ServiceAccountCreds) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CreateServiceAccountCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(201)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
+
+/*CreateServiceAccountDefault Generic error response.
+
+swagger:response createServiceAccountDefault
+*/
+type CreateServiceAccountDefault struct {
+ _statusCode int
+
+ /*
+ In: Body
+ */
+ Payload *models.Error `json:"body,omitempty"`
+}
+
+// NewCreateServiceAccountDefault creates CreateServiceAccountDefault with default headers values
+func NewCreateServiceAccountDefault(code int) *CreateServiceAccountDefault {
+ if code <= 0 {
+ code = 500
+ }
+
+ return &CreateServiceAccountDefault{
+ _statusCode: code,
+ }
+}
+
+// WithStatusCode adds the status to the create service account default response
+func (o *CreateServiceAccountDefault) WithStatusCode(code int) *CreateServiceAccountDefault {
+ o._statusCode = code
+ return o
+}
+
+// SetStatusCode sets the status to the create service account default response
+func (o *CreateServiceAccountDefault) SetStatusCode(code int) {
+ o._statusCode = code
+}
+
+// WithPayload adds the payload to the create service account default response
+func (o *CreateServiceAccountDefault) WithPayload(payload *models.Error) *CreateServiceAccountDefault {
+ o.Payload = payload
+ return o
+}
+
+// SetPayload sets the payload to the create service account default response
+func (o *CreateServiceAccountDefault) SetPayload(payload *models.Error) {
+ o.Payload = payload
+}
+
+// WriteResponse to the client
+func (o *CreateServiceAccountDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
+
+ rw.WriteHeader(o._statusCode)
+ if o.Payload != nil {
+ payload := o.Payload
+ if err := producer.Produce(rw, payload); err != nil {
+ panic(err) // let the recovery middleware deal with this
+ }
+ }
+}
diff --git a/restapi/operations/user_api/create_service_account_urlbuilder.go b/restapi/operations/user_api/create_service_account_urlbuilder.go
new file mode 100644
index 0000000000..6779391dd1
--- /dev/null
+++ b/restapi/operations/user_api/create_service_account_urlbuilder.go
@@ -0,0 +1,104 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// 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 .
+//
+
+package user_api
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the generate command
+
+import (
+ "errors"
+ "net/url"
+ golangswaggerpaths "path"
+)
+
+// CreateServiceAccountURL generates an URL for the create service account operation
+type CreateServiceAccountURL struct {
+ _basePath string
+}
+
+// WithBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *CreateServiceAccountURL) WithBasePath(bp string) *CreateServiceAccountURL {
+ o.SetBasePath(bp)
+ return o
+}
+
+// SetBasePath sets the base path for this url builder, only required when it's different from the
+// base path specified in the swagger spec.
+// When the value of the base path is an empty string
+func (o *CreateServiceAccountURL) SetBasePath(bp string) {
+ o._basePath = bp
+}
+
+// Build a url path and query string
+func (o *CreateServiceAccountURL) Build() (*url.URL, error) {
+ var _result url.URL
+
+ var _path = "/service-accounts"
+
+ _basePath := o._basePath
+ if _basePath == "" {
+ _basePath = "/api/v1"
+ }
+ _result.Path = golangswaggerpaths.Join(_basePath, _path)
+
+ return &_result, nil
+}
+
+// Must is a helper function to panic when the url builder returns an error
+func (o *CreateServiceAccountURL) Must(u *url.URL, err error) *url.URL {
+ if err != nil {
+ panic(err)
+ }
+ if u == nil {
+ panic("url can't be nil")
+ }
+ return u
+}
+
+// String returns the string representation of the path with query string
+func (o *CreateServiceAccountURL) String() string {
+ return o.Must(o.Build()).String()
+}
+
+// BuildFull builds a full url with scheme, host, path and query string
+func (o *CreateServiceAccountURL) BuildFull(scheme, host string) (*url.URL, error) {
+ if scheme == "" {
+ return nil, errors.New("scheme is required for a full url on CreateServiceAccountURL")
+ }
+ if host == "" {
+ return nil, errors.New("host is required for a full url on CreateServiceAccountURL")
+ }
+
+ base, err := o.Build()
+ if err != nil {
+ return nil, err
+ }
+
+ base.Scheme = scheme
+ base.Host = host
+ return base, nil
+}
+
+// StringFull returns the string representation of a complete url
+func (o *CreateServiceAccountURL) StringFull(scheme, host string) string {
+ return o.Must(o.BuildFull(scheme, host)).String()
+}
diff --git a/restapi/user_login.go b/restapi/user_login.go
index 9e07f21ea3..485556d4e9 100644
--- a/restapi/user_login.go
+++ b/restapi/user_login.go
@@ -44,19 +44,19 @@ func registerLoginHandlers(api *operations.McsAPI) {
})
}
-var ErrInvalidCredentials = errors.New("invalid minioCredentials")
+var errInvalidCredentials = errors.New("invalid minioCredentials")
// login performs a check of minioCredentials against MinIO
func login(credentials MCSCredentials) (*string, error) {
// try to obtain minioCredentials,
tokens, err := credentials.Get()
if err != nil {
- return nil, ErrInvalidCredentials
+ return nil, errInvalidCredentials
}
// if we made it here, the minioCredentials work, generate a jwt with claims
jwt, err := auth.NewJWTWithClaimsForClient(&tokens, getMinIOServer())
if err != nil {
- return nil, ErrInvalidCredentials
+ return nil, errInvalidCredentials
}
return &jwt, nil
}
diff --git a/restapi/user_service_accounts.go b/restapi/user_service_accounts.go
new file mode 100644
index 0000000000..3dba3016fa
--- /dev/null
+++ b/restapi/user_service_accounts.go
@@ -0,0 +1,86 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// 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 .
+
+package restapi
+
+import (
+ "bytes"
+ "context"
+ "log"
+ "strings"
+ "time"
+
+ "github.com/go-openapi/runtime/middleware"
+ "github.com/go-openapi/swag"
+ "github.com/minio/mcs/models"
+ "github.com/minio/mcs/restapi/operations"
+ "github.com/minio/mcs/restapi/operations/user_api"
+ iampolicy "github.com/minio/minio/pkg/iam/policy"
+)
+
+func registerServiceAccountsHandlers(api *operations.McsAPI) {
+ // Create Service Account
+ api.UserAPICreateServiceAccountHandler = user_api.CreateServiceAccountHandlerFunc(func(params user_api.CreateServiceAccountParams, principal *models.Principal) middleware.Responder {
+ sessionID := string(*principal)
+ creds, err := getCreateServiceAccountResponse(sessionID, params.Body)
+ if err != nil {
+ return user_api.NewCreateServiceAccountDefault(500).WithPayload(&models.Error{Code: 500, Message: swag.String(err.Error())})
+ }
+ return user_api.NewCreateServiceAccountCreated().WithPayload(creds)
+ })
+}
+
+// createServiceAccount adds a service account to the userClient and assigns a policy to him if defined.
+func createServiceAccount(ctx context.Context, userClient MinioAdmin, policy string) (*models.ServiceAccountCreds, error) {
+ iamPolicy := &iampolicy.Policy{}
+ if strings.TrimSpace(policy) != "" {
+ iamp, err := iampolicy.ParseConfig(bytes.NewReader([]byte(policy)))
+ if err != nil {
+ return nil, err
+ }
+ iamPolicy = iamp
+ }
+
+ creds, err := userClient.addServiceAccount(ctx, iamPolicy)
+ if err != nil {
+ return nil, err
+ }
+ return &models.ServiceAccountCreds{AccessKey: creds.AccessKey, SecretKey: creds.SecretKey}, nil
+}
+
+// getCreateServiceAccountResponse creates a service account with the defined policy for the user that
+// is requestingit ,it first gets the credentials of the user and creates a client which is going to
+// make the call to create the Service Account
+func getCreateServiceAccountResponse(userSessionID string, serviceAccount *models.ServiceAccount) (*models.ServiceAccountCreds, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
+ defer cancel()
+
+ userAdmin, err := newMAdminClient(userSessionID)
+ if err != nil {
+ log.Println("error creating user Client:", err)
+ return nil, err
+ }
+ // create a MinIO user Admin Client interface implementation
+ // defining the client to be used
+ userAdminClient := adminClient{client: userAdmin}
+
+ saCreds, err := createServiceAccount(ctx, userAdminClient, serviceAccount.Policy)
+ if err != nil {
+ log.Println("error creating service account:", err)
+ return nil, err
+ }
+ return saCreds, nil
+}
diff --git a/restapi/user_service_accounts_test.go b/restapi/user_service_accounts_test.go
new file mode 100644
index 0000000000..6755b0c2ed
--- /dev/null
+++ b/restapi/user_service_accounts_test.go
@@ -0,0 +1,86 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2020 MinIO, Inc.
+//
+// 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 .
+
+package restapi
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "errors"
+
+ "github.com/minio/minio/pkg/auth"
+ iampolicy "github.com/minio/minio/pkg/iam/policy"
+ "github.com/stretchr/testify/assert"
+)
+
+// assigning mock at runtime instead of compile time
+var minioAddServiceAccountMock func(ctx context.Context, policy *iampolicy.Policy) (auth.Credentials, error)
+
+// mock function of listUsers()
+func (ac adminClientMock) addServiceAccount(ctx context.Context, policy *iampolicy.Policy) (auth.Credentials, error) {
+ return minioAddServiceAccountMock(ctx, policy)
+}
+
+func TestAddServiceAccount(t *testing.T) {
+ assert := assert.New(t)
+ // mock minIO client
+ client := adminClientMock{}
+ function := "createServiceAccount()"
+ // Test-1: createServiceAccount create a service account by assigning it a policy
+ ctx := context.Background()
+ policyDefinition := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"s3:GetBucketLocation\",\"s3:GetObject\",\"s3:ListAllMyBuckets\"],\"Resource\":[\"arn:aws:s3:::bucket1/*\"]}]}"
+ mockResponse := auth.Credentials{
+ AccessKey: "minio",
+ SecretKey: "minio123",
+ }
+ minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy) (auth.Credentials, error) {
+ return mockResponse, nil
+ }
+ saCreds, err := createServiceAccount(ctx, client, policyDefinition)
+ if err != nil {
+ t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
+ }
+ assert.Equal(mockResponse.AccessKey, saCreds.AccessKey, fmt.Sprintf("Failed on %s:, error occurred: AccessKey differ", function))
+ assert.Equal(mockResponse.SecretKey, saCreds.SecretKey, fmt.Sprintf("Failed on %s:, error occurred: SecretKey differ", function))
+
+ // Test-2: if an invalid policy is assigned to the service account, this will raise an error
+ policyDefinition = "invalid policy"
+ mockResponse = auth.Credentials{
+ AccessKey: "minio",
+ SecretKey: "minio123",
+ }
+ minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy) (auth.Credentials, error) {
+ return mockResponse, nil
+ }
+ saCreds, err = createServiceAccount(ctx, client, policyDefinition)
+ assert.Error(err)
+
+ // Test-3: if an error occurs on server while creating service account (valid policy), handle it
+ policyDefinition = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"s3:GetBucketLocation\",\"s3:GetObject\",\"s3:ListAllMyBuckets\"],\"Resource\":[\"arn:aws:s3:::bucket1/*\"]}]}"
+ mockResponse = auth.Credentials{
+ AccessKey: "minio",
+ SecretKey: "minio123",
+ }
+ minioAddServiceAccountMock = func(ctx context.Context, policy *iampolicy.Policy) (auth.Credentials, error) {
+ return auth.Credentials{}, errors.New("error")
+ }
+ _, err = createServiceAccount(ctx, client, policyDefinition)
+ if assert.Error(err) {
+ assert.Equal("error", err.Error())
+ }
+}
diff --git a/restapi/utils.go b/restapi/utils.go
index 7bcf98a7b0..e8d735e939 100644
--- a/restapi/utils.go
+++ b/restapi/utils.go
@@ -31,7 +31,7 @@ func DifferenceArrays(a, b []string) []string {
return diff
}
-// IsElementInSlice returns true if the string belongs to the slice
+// IsElementInArray returns true if the string belongs to the slice
func IsElementInArray(a []string, b string) bool {
for _, e := range a {
if e == b {
diff --git a/swagger.yml b/swagger.yml
index fd5d108c10..d9cae8806c 100644
--- a/swagger.yml
+++ b/swagger.yml
@@ -284,6 +284,28 @@ paths:
tags:
- UserAPI
+ /service-accounts:
+ post:
+ summary: Create Service Account
+ operationId: CreateServiceAccount
+ parameters:
+ - name: body
+ in: body
+ required: true
+ schema:
+ $ref: '#/definitions/serviceAccount'
+ responses:
+ 201:
+ description: A successful response.
+ schema:
+ $ref: "#/definitions/serviceAccountCreds"
+ default:
+ description: Generic error response.
+ schema:
+ $ref: "#/definitions/error"
+ tags:
+ - UserAPI
+
/users:
get:
summary: List Users
@@ -1312,3 +1334,17 @@ definitions:
type: array
items:
type: string
+ serviceAccount:
+ type: object
+ properties:
+ policy:
+ type: string
+ title : "policy to be applied to the Service Account if any"
+ serviceAccountCreds:
+ type: object
+ properties:
+ accessKey:
+ type: string
+ secretKey:
+ type: string
+