Compare commits

...

113 Commits

Author SHA1 Message Date
Cesar N
44551ac292 Add create zone for tenant api (#194) 2020-07-13 20:36:27 -07:00
Lenin Alevski
697bc4cd1d Refactor for session management (#193)
Previously every Handler function was receiving the session token in the
form of a jwt string, in consequence every time we want to access the
encrypted claims of the jwt we needed to run a decryption process,
additionally we were decrypting the jwt twice, first at the session
validation then inside each handler function, this was also causing a
lot of using related to the merge between m3 and mcs

What changed:

Now we validate and decrypt the jwt once in `configure_mcs.go`, this
works for both, mcs (console) and operator sessions, and then pass the
decrypted claims to all the functions that need it, so no further token
validation or decryption is need it.
2020-07-10 19:14:28 -07:00
Cesar N
93e1168141 Add fields to tenant's info api (#192)
The response includes Image, TotalSize which is the available size
and UsedSize which is the real Disk Space
2020-07-09 12:24:01 -07:00
Daniel Valdivia
328133d3ff Fix Session validation for MCS Operator Mode (#191)
* Fix Session validation for MCS Operator Mode

* Updated assets
2020-07-08 13:55:08 -07:00
Cesar N
8a74b795c8 Add kubernetes kustomize yaml files (#188) 2020-07-02 21:33:55 -07:00
Daniel Valdivia
b7614b66d2 Merge M3 into MCS (#187)
* Merge M3 into MCS

* Fix Linting

* Add missing cluster folder
2020-07-01 18:03:22 -07:00
Daniel Valdivia
be069eddd5 Small Tweaks (#186)
* Support for MinDNS

* mindns option

* Added minDNS to summary table

* Validations of configure page

* Added create label & removed console logs

* Adding login workaround

* Added min limits to inputs

* Fixed issue with sizes

* Removed empty values from review page

* Added zone names

* Added validation to zones selector

* Fixed issue with back button in zones page

* Changed validation for zones filter & simplified clean zones

* Changed CredentialsPrompt to be a global component.

* Added assets

* Added hover to table & removed view button

* Added view links & actions to tables

* Added links for cloud & console in table

* Fixed position of progress bar

* Added advanced mode to wizard

* Added "zebra-style" tables

* Added servers field to simple form

* Fixes for demo

* Tweaks

* updated assets

* remove hardcoded bypass

* Address Comments

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-07-01 11:58:35 -07:00
Lenin Alevski
59a5c9dbf0 Fix login and logout flow for MCS (#185)
fixes: https://github.com/minio/mcs/issues/184

There was a bug in Safari in related to the browser not setting the session token
correctly in localstorage, this was because we were using
window.location.href for redirect instead of history.push after login, the redirect execution was faster
was faster that the promise function getting the response after the login request
and it seems to be that Safari will kill all current request of a
window when the page is getting redirected.

Test this:

Try to sign-in using Safari browser (latest version is recommended)
2020-06-29 20:58:56 -07:00
Lenin Alevski
1e7f272a67 MCS service account authentication with Mkube (#166)
`MCS` will authenticate against `Mkube`using bearer tokens via HTTP
`Authorization` header. The user will provide this token once
in the login form, MCS will validate it against Mkube (list tenants) and
if valid will generate and return a new MCS sessions
with encrypted claims (the user Service account token will be inside the
JWT in the data field)

Kubernetes

The provided `JWT token` corresponds to the `Kubernetes service account`
that `Mkube` will use to run tasks on behalf of the
user, ie: list, create, edit, delete tenants, storage class, etc.

Development

If you are running mcs in your local environment and wish to make
request to `Mkube` you can set `MCS_M3_HOSTNAME`, if
the environment variable is not present by default `MCS` will use
`"http://m3:8787"`, additionally you will need to set the
`MCS_MKUBE_ADMIN_ONLY=on` variable to make MCS display the Mkube UI

Extract the Service account token and use it with MCS

For local development you can use the jwt associated to the `m3-sa`
service account, you can get the token running
the following command in your terminal:

```
kubectl get secret $(kubectl get serviceaccount m3-sa -o
jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" | base64
--decode
```

Then run the mcs server

```
MCS_M3_HOSTNAME=http://localhost:8787 MCS_MKUBE_ADMIN_ONLY=on ./mcs
server
```

Self-signed certificates and Custom certificate authority for Mkube

If Mkube uses TLS with a self-signed certificate, or a certificate
issued by a custom certificate authority you can add those
certificates usinng the `MCS_M3_SERVER_TLS_CA_CERTIFICATE` env variable

````
MCS_M3_SERVER_TLS_CA_CERTIFICATE=cert1.pem,cert2.pem,cert3.pem ./mcs
server
````
2020-06-23 11:37:46 -07:00
César Nieto
1aec2d879e Remove unused swagger autogenerated files (#180) 2020-06-22 20:56:52 -07:00
Alex
f77770bb6e Changed create tenant form to be a wizard (#179) 2020-06-22 12:21:19 -05:00
Alex
34ff3d7157 Implemented validation in create tenant form (#177)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-06-19 11:16:16 -07:00
Alex
4b6700d4ac Fixed usability issues on IAM Policies module (#175)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-06-15 21:38:42 -07:00
Alex
f2c8f15fbf Added delete option to multi-zone selector (#167)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-06-15 16:29:43 -07:00
Anton Huck
991204cd46 Remove trailing comma in policy (#160)
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
Co-authored-by: César Nieto <ces.nietor@gmail.com>
Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
Co-authored-by: Lenin Alevski <alevsk.8772@gmail.com>
2020-06-08 19:24:51 -07:00
Justin Hutchings
4bac7040a1 Add CodeQL security scanning (#157)
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
2020-06-08 17:44:22 -07:00
dependabot[bot]
a247bf6a0c Bump websocket-extensions from 0.1.3 to 0.1.4 in /portal-ui (#165)
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-06-08 14:04:18 -07:00
Daniel Valdivia
f4d08a7502 Tenant Details (#162) 2020-06-08 13:37:14 -07:00
Daniel Valdivia
fb59e8c353 Remove Policy OPA (#164) 2020-06-04 18:37:59 -07:00
Daniel Valdivia
6e6ed300b7 Listen to all ips by default (#161) 2020-06-04 15:57:13 -07:00
Harshavardhana
48e6b1bb7c stick to go1.13 for now, update credits (#163)
fix release tags for mcs
2020-06-04 13:15:56 -07:00
César Nieto
8949fbe245 Integrate mkube storageclass api with UI (#156) 2020-06-04 11:22:33 -07:00
Daniel Valdivia
d8e6bd7f4a Fix Add Tenant Image and Delete Tenant URL (#155) 2020-06-04 11:00:28 -07:00
Alex
4edfeb22c6 Removed horizontal scrollbar in menu (#159) 2020-06-04 10:05:04 -07:00
Alex
2d5d0d16ca Changed menu design for mcs (#158)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-06-03 18:56:48 -07:00
César Nieto
16f8ee485a add logs to mkube api handler (#154) 2020-06-02 20:07:58 -07:00
Daniel Valdivia
2d28f8bf35 Pass Storage Class when adding a tenant (#153) 2020-06-02 13:24:07 -05:00
Daniel Valdivia
8af3665ae2 Connect List,Add Tenants (#148) 2020-06-02 11:52:37 -05:00
Daniel Valdivia
0fa1d4bf7c Update Menu with Tools section (#147)
Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
2020-05-28 15:03:29 -07:00
Daniel Valdivia
8139416323 Proxy API For Mkube (#145) 2020-05-27 15:46:18 -07:00
Alex
be5cd7f148 Added flag for operator only features (#144)
Added flag to only enable operator endpoints / links in mcs
2020-05-26 19:35:44 -07:00
César Nieto
fa068b6d4a Add admin heal api and ui (#142) 2020-05-26 17:28:14 -07:00
Alex
a805a49662 Added loaders to bucket information block (#141)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-22 22:46:42 -07:00
Daniel Valdivia
296e4ff5ce Set Policy For Groups (#140) 2020-05-22 16:09:24 -07:00
Alex
20749d2eae Implemented calculation for zone size in zone modal (#137) 2020-05-22 14:49:42 -05:00
Alex
ff4e959d11 Fixed styles in users policy modal (#139)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-22 12:36:41 -07:00
Daniel Valdivia
37195fefa8 Set Policy UI (#138) 2020-05-22 08:48:55 -07:00
Alex
13ef83cee4 Added Clusters mockups (#133) 2020-05-21 20:03:36 -05:00
Alex
b89b2d0c6a Changed bucket detail styles & minor fixes (#136)
Changed bucket detail styles & fixed minor issues for edit access policy & usage report not shown in page

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-21 17:19:50 -07:00
Daniel Valdivia
edf687fd8a Loading text on TableWrapper (#135) 2020-05-21 16:49:31 -07:00
Daniel Valdivia
cb60eba373 Landing images (#134) 2020-05-21 12:55:30 -07:00
Daniel Valdivia
c49a7bbe3c Add details on Policy for Service Account (#132) 2020-05-21 12:11:16 -07:00
Alex
3bb317535c Added path to bucket details in acls list (#131) 2020-05-20 21:59:03 -05:00
Alex
989e6f3471 Added Service Accounts page to settings (#128)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-19 13:41:46 -07:00
Lenin Alevski
35d575e7ac Allow sign-in users without policy (#129) 2020-05-19 15:26:53 -05:00
Harshavardhana
92a8aab07d upgrade linter and cleanup makefile (#126) 2020-05-18 21:55:54 -07:00
César Nieto
c5b2419191 Fix websocket apis (#127)
Remove ping check and instead use a context that will be canceled
if it the client sends a close message or an error occurs on reading.
The context will be used to cancel all functions using it.
2020-05-18 21:21:02 -07:00
Lenin Alevski
732e0ef683 ACL for mcs (#123)
This PR sets the initial version of the ACL for mcs, the idea behind
this is to start using the principle of least privileges when assigning
policies to users when creating users through mcs, currently mcsAdmin policy uses admin:*
and s3:* and by default a user with that policy will have access to everything, if want to limit
that we can create a policy with least privileges.

We need to start validating explicitly if users has acccess to an
specific endpoint based on IAM policy actions.

In this first version every endpoint (you can see it as a page to),
defines a set of well defined admin/s3 actions to work properly, ie:

```
// corresponds to /groups endpoint used by the groups page
var groupsActionSet = iampolicy.NewActionSet(
    iampolicy.ListGroupsAdminAction,
    iampolicy.AddUserToGroupAdminAction,
    //iampolicy.GetGroupAdminAction,
    iampolicy.EnableGroupAdminAction,
    iampolicy.DisableGroupAdminAction,
)

// corresponds to /policies endpoint used by the policies page
var iamPoliciesActionSet = iampolicy.NewActionSet(
    iampolicy.GetPolicyAdminAction,
    iampolicy.DeletePolicyAdminAction,
    iampolicy.CreatePolicyAdminAction,
    iampolicy.AttachPolicyAdminAction,
    iampolicy.ListUserPoliciesAdminAction,
)
```
With that said, for this initial version, now the sessions endpoint will
return a list of authorized pages to be render on the UI, on subsequent
prs we will add this verification of authorization via a server
middleware.
2020-05-18 18:03:06 -07:00
César Nieto
e8491d80cb Add size info to bucket list api (#122)
Using madmin.AccountUsageInfo since that api
includes size already.
Also includes integration with UI.
2020-05-18 13:36:18 -07:00
Daniel Valdivia
35c3b53a23 Dashboard Loading + Prettier files (#124) 2020-05-15 14:41:27 -07:00
César Nieto
6fef30f29d Add Watch api and UI integration (#120)
Uses a similar approach as Trace and Console Logs by using
websockets. It also includes the integration with the UI which
needs 3 input fields that are sent as query parameters.
2020-05-15 14:24:29 -07:00
Alex
acf480fd25 Changed help icon position next to label (#119) 2020-05-12 19:54:24 -05:00
César Nieto
8bbc4f0192 remove color dependency and any non ascii characters (#118) 2020-05-12 17:20:58 -07:00
Alex
48e7991f11 Fixed label size & added text alignment (#112)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-12 14:34:48 -07:00
Alex
5e9b0652b0 Changed modal forms to contain scrollbars (#113)
Changed modal forms to contain scrollbars where the inputs are, so this way the titles and buttons get always visible.

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
2020-05-12 13:41:09 -05:00
Lenin Alevski
438211199d LDAP authentication support for MCS (#114)
This PR adds ldap authentication support for mcs based on
https://github.com/minio/minio/blob/master/docs/sts/ldap.md

How to test:

```
$ docker run --rm -p 389:389 -p 636:636 --name my-openldap-container
--detach osixia/openldap:1.3.0
```

Run the `billy.ldif` file using `ldapadd` command to create a new user
and assign it to a group.

```
$ cat > billy.ldif << EOF
dn: uid=billy,dc=example,dc=org
uid: billy
cn: billy
sn: 3
objectClass: top
objectClass: posixAccount
objectClass: inetOrgPerson
loginShell: /bin/bash
homeDirectory: /home/billy
uidNumber: 14583102
gidNumber: 14564100
userPassword: {SSHA}j3lBh1Seqe4rqF1+NuWmjhvtAni1JC5A
mail: billy@example.org
gecos: Billy User
dn: ou=groups,dc=example,dc=org
objectclass:organizationalunit
ou: groups
description: generic groups branch
of s3::*)
dn: cn=mcsAdmin,ou=groups,dc=example,dc=org
objectClass: top
objectClass: posixGroup
gidNumber: 678
dn: cn=mcsAdmin,ou=groups,dc=example,dc=org
changetype: modify
add: memberuid
memberuid: billy
EOF

$ docker cp billy.ldif
my-openldap-container:/container/service/slapd/assets/test/billy.ldif
$ docker exec my-openldap-container ldapadd -x -D
"cn=admin,dc=example,dc=org" -w admin -f
/container/service/slapd/assets/test/billy.ldif -H ldap://localhost -ZZ
```

Query the ldap server to check the user billy was created correctly and
got assigned to the mcsAdmin group, you should get a list
containing ldap users and groups.

```
$ docker exec my-openldap-container ldapsearch -x -H ldap://localhost -b
dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
```

Query the ldap server again, this time filtering only for the user
`billy`, you should see only 1 record.

```
$ docker exec my-openldap-container ldapsearch -x -H ldap://localhost -b
uid=billy,dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
```

Change the password for user billy

Set the new password for `billy` to `minio123` and enter `admin` as the
default `LDAP Password`

```
$ docker exec -it my-openldap-container /bin/bash
ldappasswd -H ldap://localhost -x -D "cn=admin,dc=example,dc=org" -W
-S "uid=billy,dc=example,dc=org"
New password:
Re-enter new password:
Enter LDAP Password:
```

Add the mcsAdmin policy to user billy on MinIO

```
$ cat > mcsAdmin.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "admin:*"
      ],
      "Effect": "Allow",
      "Sid": ""
    },
    {
      "Action": [
        "s3:*"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::*"
      ],
      "Sid": ""
    }
  ]
}
EOF
$ mc admin policy add myminio mcsAdmin mcsAdmin.json
$ mc admin policy set myminio mcsAdmin user=billy
```

Run MinIO

```
export MINIO_ACCESS_KEY=minio
export MINIO_SECRET_KEY=minio123
export MINIO_IDENTITY_LDAP_SERVER_ADDR='localhost:389'
export MINIO_IDENTITY_LDAP_USERNAME_FORMAT='uid=%s,dc=example,dc=org'
export
MINIO_IDENTITY_LDAP_USERNAME_SEARCH_FILTER='(|(objectclass=posixAccount)(uid=%s))'
export MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY=on
export MINIO_IDENTITY_LDAP_SERVER_INSECURE=on
./minio server ~/Data
```

Run MCS

```
export MCS_ACCESS_KEY=minio
export MCS_SECRET_KEY=minio123
...
export MCS_LDAP_ENABLED=on
./mcs server
```
2020-05-12 10:26:38 -07:00
Alex
0f77a32656 Fixed delete bucket event functionality (#109)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-09 10:16:15 -07:00
Daniel Valdivia
9f3e99ede8 Fix UI Metadata (#108) 2020-05-08 19:38:51 -07:00
Lenin Alevski
a8c07c0969 Connect MCS with Minio insecure TLS/Custom CAs (#102)
This PR adds support to connect MCS to minio instances running TLS with
self-signed certificates or  certificates signed by custom
Certificate Authorities

```
export MCS_MINIO_SERVER_TLS_ROOT_CAS=file1,file2,file3
```

Note: TLS Skip Verification is not supported unless there's a clear need
for it
2020-05-08 17:11:47 -07:00
Daniel Valdivia
cf8472b04c wss for websockets on tls and single page application behavior (#107) 2020-05-08 16:36:08 -07:00
Alex
317a7ebbd3 Fixed error messages in mcs (#105)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-08 12:31:09 -07:00
Alex
63f4150232 Added pagination to users page (#100)
Added pagination to users page for mcs, this resolves #96

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-06 21:47:41 -07:00
César Nieto
3bfc2556fc authenticate websocket apis using sts (#97) 2020-05-06 16:47:49 -05:00
César Nieto
511cc47d2b Add console logs api and integrate it with UI (#90)
Uses same behavior as the Trace feature using websockets.
For displaying it on the UI it needed to handle colors
since the log message comes with unicode colors embbeded
on the message.
Also a special case when an error log comes needed to be handled
to show all sources of the error.
2020-05-05 15:12:04 -07:00
Alex
9660650f41 Settings forms connection (#95)
Connected the forms to backend to send & receive the information stored in MinIO settings

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-05-05 11:07:06 -07:00
Lenin Alevski
9ac754d4de MCS use the correct region to authenticate users (#94)
Previous mcs was authenticating all the users agains <empty> region,
this was a problem when an admin configure a different region via the
configuration page on mcs, now before authenticating a user via
credentials or idp mcs will ask minio what's the current region and try
to authenticate using that that information.

- Login to mcs
- Go to the configuration page and change the region, ie: us-west-1
- Logout from mcs
- Login to mcs again, you should not get any error
2020-05-04 18:18:04 -05:00
César Nieto
646318e1f6 Add list and delete service accounts api (#91) 2020-05-04 15:48:38 -07:00
César Nieto
beb1ac7d04 add CREDITS file (#93) 2020-05-04 15:41:16 -07:00
César Nieto
f3a9311374 add comments to exported functions (#92) 2020-05-04 15:28:49 -07:00
Lenin Alevski
44d8e9b975 idp integration for mcs (#75)
This PR adds support for oidc in  mcs, to enable idp
authentication you need to pass the following environment variables and
restart mcs.

```
MCS_IDP_URL=""
MCS_IDP_CLIENT_ID=""
MCS_IDP_SECRET=""
MCS_IDP_CALLBACK=""
```
2020-05-01 08:38:52 -07:00
Alex
f3d7e61ddb Updated material-ui dependency (#88)
Updated material-ui dependency and fixed a couple os issues that could cause the application to crash
2020-04-30 18:11:34 -07:00
Daniel Valdivia
526c0f4796 UI utils file (#87) 2020-04-30 12:19:33 -07:00
Daniel Valdivia
fe1acaa4b6 Admin Trace UI (#86) 2020-04-30 11:53:50 -07:00
César Nieto
8e9bd8728a Add mcs admin trace api (#82)
Trace Api uses websocket to send trace information, a
valid jwt token needs to be sent either on the header
or as a cookie of the ws request to start.
Three goroutines are needed to ensure communication
if read hearbeat fails all trace should stop by cancelling
the context. WaitGroups are needed to ensure all
goroutines finish gracefully.
2020-04-30 10:50:51 -07:00
Alex
9df9309c66 Configuration List Forms (#83)
Created Lists & forms for configurations in mcs
2020-04-30 00:00:02 -05:00
César Nieto
b85712e29e Add Create Service Account api (#72)
adds new functionality for creating a service
account for a user, for this, an admin client
is created with the user credentials so that
the service account can be assigned to him.

This also updates to  minio RELEASE.2020-04-28T23-56-56Z
2020-04-29 18:28:28 -07:00
Daniel Valdivia
c32df86c76 use target implementation on config api (#81)
Co-authored-by: Cesar Nieto <ces.nietor@gmail.com>
2020-04-29 10:54:59 -07:00
Lenin Alevski
0f52136fd2 STS integration, JWT auth and Stateless MCS (#70)
This commit changes the authentication mechanism between mcs and minio to an sts
(security token service) schema using the user provided credentials, previously
mcs was using master credentials. With that said in order for you to
login to MCS as an admin your user must exists first on minio and have enough
privileges to do administrative operations.

```
./mc admin user add myminio alevsk alevsk12345
```

```
cat admin.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "admin:*",
        "s3:*"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ]
    }
  ]
}

./mc admin policy add myminio admin admin.json
```

```
./mc admin policy set myminio admin user=alevsk
```
2020-04-22 23:43:17 -07:00
Alex
605b80037a Fixed users list issue (#80)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-22 16:40:27 -07:00
Daniel Valdivia
63b430e354 Bug: User List not refreshing after delete (#79) 2020-04-21 17:48:55 -05:00
Alex
d9c212fe2f Tables replacement in mcs (#74)
Replaced all the tables in mcs to be consistent with the new design

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-21 15:38:46 -07:00
Daniel Valdivia
5fa0a0fca8 Bug: SSL Mode options for Postgres (#77) 2020-04-21 13:34:15 -07:00
Daniel Valdivia
068ac281ea UI Add Notification Targets (#73) 2020-04-20 20:53:58 -07:00
Alex
0bcf88eb7c Table component implementation (#71)
Implementation of a new table wrapper component that will be used across the application.

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-18 08:16:17 -07:00
César Nieto
5c137a8678 Update mcs to latest minio and mc (#69)
updates code to be compatible with:
- github.com/minio/mc v0.0.0-20200415193718-68b638f2f96c
- github.com/minio/minio v0.0.0-20200415191640-bde0f444dbab

Note: admin_config api is patched temporarily now to
return the target configuration as a raw string due to the
changes done on minio.
2020-04-16 13:56:12 -07:00
Alex
540ff31784 Added bulk functionality for add users to groups (#68)
Added functionality in users module to add multiple users to multiple groups at once.

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-15 18:08:35 -07:00
Daniel Valdivia
82ea3c1ac4 UI list Lambda Notification Targets (#67) 2020-04-14 14:52:59 -07:00
Alex
e1f177257a Updated form dialog components to be using ModalBoxWrapper component (#66)
Updated all form dialog components in mcs to be using the new ModalBoxWrapper component, This doesn't affect delete dialogs since we are going to create an independent component for those.

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-13 22:27:34 -07:00
Alex
0211827c74 Removed console messages in mcs-users module (#65)
Removed console messages in mcs-users module
2020-04-13 17:06:43 -07:00
Daniel Valdivia
ac5732970c New Logo (#64) 2020-04-13 10:59:46 -07:00
Alex
1b1ed55252 Creation of reusable components for mcs & implementation in users page (#63)
Creation of reusable componentes for mcs:
- ModalWrapper => Modal box component with MinIO styles
- InputBoxWrapper => Input box component with MinIO styles
- RadioGroupSelector => Component that generates a Radio Group Selector combo with the requested options and MinIO styles

Implementation of these new components in users creation / edit components

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-10 22:13:31 -07:00
Alex
5c5e84b289 Implemented User-Groups integration for mcs (#62)
Implemented user-groups integration for mcs, this allows to store the user groups during the user creation.

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-09 16:39:49 -07:00
Daniel Valdivia
5755b98b66 API to list and add Notification Endpoints (#50) 2020-04-09 16:07:26 -07:00
Harshavardhana
86ee1eea6d add code of conduct, contributing and security guidelines (#61) 2020-04-09 12:04:15 -07:00
Harshavardhana
adcbf61049 add support for mcs build to trim gopaths (#60)
also remove `version` sub-command as we don't
use this anymore, just use `mcs --version`
2020-04-09 11:29:49 -07:00
Alex
e197399441 Users-Group Update API (#49)
* Added structure to swagger

* Added updateUserGroups handlers

* Updated return definition for user groups.

* Logic rewrite

* Removed logs

* Added some tests to updateUserGroups

* lint fix

* Updated tests for the new API

* Lint

* Added comment about why we are setting this groups individually. & more lint fixes

* Updated tests page

* Added more tests & fixed comments for PR

* Lint utils file

* Fixed import orders

* Changed import order

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-08 17:38:18 -07:00
Lenin Alevski
ff2438a877 Logout endpoint (#47)
Delete in memory session when user logout from mcs

lint fixes

Click logout button triggers logout request

Clicking the actual logout button send the POST /logout request on mcs
UI

Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
2020-04-08 14:36:14 -05:00
César Nieto
c85067dfba UI remove setting access on make bucket (#46)
Remove CUSTOM option on access to set
2020-04-08 07:44:32 -07:00
Daniel Valdivia
b1df170d80 Change font to Lato (#48) 2020-04-07 17:31:26 -07:00
Daniel Valdivia
9566f6e579 Fix Groups Empty (#45) 2020-04-07 13:29:40 -07:00
Daniel Valdivia
12a682e9f6 Redirect to Login when not logged in. (#44) 2020-04-07 11:56:52 -07:00
César Nieto
e0bb098e47 mcs delete bucket event notification api (#36)
Co-authored-by: Lenin Alevski <alevsk.8772@gmail.com>
2020-04-07 09:27:25 -07:00
Lenin Alevski
b390ce309a Reading policy as json string (#43)
addPolicy endpoint will read policies as json string, this to allow
s3 iam policy compatibility (uppercase in json attributes) and to be
consistent with other mcs apis, once https://github.com/minio/minio/pull/9181
is merged we can return a type struct{}

fix policies test to new refactor

goimports

more golint fixes
2020-04-06 19:10:10 -07:00
Alex
3dac86d3ce Implements remove user API (#42)
* Implementation of RemoveUser from madmin

* Added removeUser structure.

* Added removeUserResponse actions

* Added delete API to swagger

* Added tests to removeUser functions

* Removed extra space at EOF

* Changed context to be a parameter in admin_users functions

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-04-06 18:07:32 -07:00
Daniel Valdivia
2001ab6dae Logout on Unauthorized. Fix all UI warnings. (#35) 2020-04-06 16:35:30 -07:00
César Nieto
31f0655ff6 mcs add tests for groups and mock same function twice (#41) 2020-04-06 16:18:28 -07:00
César Nieto
775874cf86 update golangci-lint to v1.24 on github workflow (#40)
* update golangci-lint to v1.24 on github workflow

* fix lint errors
2020-04-06 16:04:18 -07:00
Lenin Alevski
9ca4daa906 TLS redirect enabled by default (#39)
When certificates are provided to mcs, tls direct will be
enabled by default (http://localhost -> https:localhost), you
can change this behavior by providing the `MCS_SECURE_SSL_REDIRECT=off`
env variable
2020-04-06 15:59:21 -07:00
Lenin Alevski
2318a8a82b disabling default tls redirect (#38)
Co-authored-by: César Nieto <ces.nietor@gmail.com>
2020-04-06 15:22:39 -07:00
Daniel Valdivia
69ed6f5ca4 Development md (#34)
* Introduce DEVELOPMENT.md

* Ignore *.orig files

Co-authored-by: Lenin Alevski <alevsk.8772@gmail.com>
2020-04-06 14:22:27 -07:00
Lenin Alevski
3a96e6d7e7 Secure Middleware (#37)
adding secure middleware to enforce security headers, most
of the options can be configured via env variables

adding prefix for mcs env variables

adding http redirect to https, adding csp report only, etc

solving conflicts

passing tls port configured by cli to secure middleware

update go.sum

adding default port, tlsport, host and tlshostname

fix tlsport bug
2020-04-06 13:24:15 -07:00
Daniel Valdivia
9a2b10476c Updated README.md (#33) 2020-04-06 12:07:40 -07:00
Daniel Valdivia
c8938dc131 Fix Module (#32) 2020-04-06 11:58:34 -07:00
490 changed files with 71673 additions and 7468 deletions

View File

@@ -3,3 +3,4 @@ dist/
target/
mcs
!mcs/
portal-ui/node_modules/

52
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: "Code scanning - action"
on:
push:
pull_request:
schedule:
- cron: '0 19 * * 0'
jobs:
CodeQL-Build:
# CodeQL runs on ubuntu-latest and windows-latest
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -14,25 +14,23 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [1.14.x]
go-version: [1.13.x, 1.14.x]
os: [ubuntu-latest]
steps:
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v1
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v1
uses: actions/checkout@v2
- name: Build on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.21.0
$(go env GOPATH)/bin/golangci-lint run --timeout=5m --config ./.golangci.yml
go mod vendor
go test -v -race ./...
make verifiers
make test
make mcs

View File

@@ -1,48 +0,0 @@
name: goreleaser
on:
pull_request:
push:
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Unshallow
run: git fetch --prune --unshallow
-
name: Set up Go
uses: actions/setup-go@v1
with:
go-version: 1.14.x
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@53acad1befee355d46f71cccf6ab4d885eb4f77f
with:
version: latest
args: release --skip-publish --rm-dist --snapshot
-
name: Upload Win64 Binaries
uses: actions/upload-artifact@v1
if: success()
with:
name: MCS-Snapshot-Build-Win64
path: dist/mcs_windows_amd64
-
name: Upload Linux Binaries
uses: actions/upload-artifact@v1
if: success()
with:
name: MCS-Snapshot-Build-Linux-amd64
path: dist/mcs_linux_amd64
-
name: Upload MacOS Binaries
uses: actions/upload-artifact@v1
if: success()
with:
name: MCS-Snapshot-Build-MacOSX-amd64
path: dist/mcs_darwin_amd64

10
.gitignore vendored
View File

@@ -6,6 +6,7 @@
*.dylib
.DS_Store
*.swp
*.orig
# Test binary, build with `go test -c`
*.test
@@ -22,3 +23,12 @@ mcs
!mcs/
dist/
# Ignore tls cert and key
private.key
public.crt
# Ignore VsCode files
.vscode/
*.code-workspace
*~

View File

@@ -1,4 +1,7 @@
linters-settings:
golint:
min-confidence: 0
misspell:
locale: US
@@ -14,4 +17,12 @@ linters:
- gosimple
- deadcode
- unparam
- unused
- structcheck
service:
golangci-lint-version: 1.21.0 # use the fixed version to not introduce new linters unexpectedly
run:
skip-dirs:
- pkg/clientgen

View File

@@ -23,7 +23,7 @@ builds:
- -trimpath
- --tags=kqueue
ldflags:
- -s -w -X github.com/minio/mcs/pkg.ReleaseTag={{.Tag}} -X github.com/minio/warp/pkg.CommitID={{.FullCommit}} -X github.com/minio/warp/pkg.Version={{.Version}} -X github.com/minio/warp/pkg.ShortCommitID={{.ShortCommit}} -X github.com/minio/warp/pkg.ReleaseTime={{.Date}}
- -s -w -X github.com/minio/mcs/pkg.ReleaseTag={{.Tag}} -X github.com/minio/mcs/pkg.CommitID={{.FullCommit}} -X github.com/minio/mcs/pkg.Version={{.Version}} -X github.com/minio/mcs/pkg.ShortCommitID={{.ShortCommit}} -X github.com/minio/mcs/pkg.ReleaseTime={{.Date}}
archives:
-
replacements:

59
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,59 @@
# MinIO Console Server Contribution Guide [![Slack](https://slack.min.io/slack?type=svg)](https://slack.min.io)
This is a REST portal server created using [go-swagger](https://github.com/go-swagger/go-swagger)
The API handlers are created using a YAML definition located in `swagger.YAML`.
To add new api, the YAML file needs to be updated with all the desired apis using the [Swagger Basic Structure](https://swagger.io/docs/specification/2-0/basic-structure/), this includes paths, parameters, definitions, tags, etc.
## Generate server from YAML
Once the YAML file is ready we can autogenerate the code needed for the new api by just running:
Validate it:
```
swagger validate ./swagger.yml
```
Update server code:
```
make swagger-gen
```
This will update all the necessary code.
`./restapi/configure_mcs.go` is a file that contains the handlers to be used by the application, here is the only place where we need to update our code to support the new apis. This file is not affected when running the swagger generator and it is safe to edit.
## Unit Tests
`./restapi/handlers_test.go` needs to be updated with the proper tests for the new api.
To run tests:
```
go test ./restapi
```
## Commit changes
After verification, commit your changes. This is a [great post](https://chris.beams.io/posts/git-commit/) on how to write useful commit messages
```
$ git commit -am 'Add some feature'
```
### Push to the branch
Push your locally committed changes to the remote origin (your fork)
```
$ git push origin my-new-feature
```
### Create a Pull Request
Pull requests can be created via GitHub. Refer to [this document](https://help.github.com/articles/creating-a-pull-request/) for detailed steps on how to create a pull request. After a Pull Request gets peer reviewed and approved, it will be merged.
## FAQs
### How does ``mcs`` manages dependencies?
``MinIO`` uses `go mod` to manage its dependencies.
- Run `go get foo/bar` in the source folder to add the dependency to `go.mod` file.
To remove a dependency
- Edit your code and remove the import reference.
- Run `go mod tidy` in the source folder to remove dependency from `go.mod` file.
### What are the coding guidelines for mcs?
``mcs`` is fully conformant with Golang style. Refer: [Effective Go](https://github.com/golang/go/wiki/CodeReviewComments) article from Golang project. If you observe offending code, please feel free to send a pull request or ping us on [Slack](https://slack.min.io).

23872
CREDITS Normal file

File diff suppressed because it is too large Load Diff

127
DEVELOPMENT.md Normal file
View File

@@ -0,0 +1,127 @@
# LDAP authentication with MCS
## Setup
Run openLDAP with docker.
```
$ docker run --rm -p 389:389 -p 636:636 --name my-openldap-container --detach osixia/openldap:1.3.0
```
Run the `billy.ldif` file using `ldapadd` command to create a new user and assign it to a group.
```
$ cat > billy.ldif << EOF
# LDIF fragment to create group branch under root
dn: uid=billy,dc=example,dc=org
uid: billy
cn: billy
sn: 3
objectClass: top
objectClass: posixAccount
objectClass: inetOrgPerson
loginShell: /bin/bash
homeDirectory: /home/billy
uidNumber: 14583102
gidNumber: 14564100
userPassword: {SSHA}j3lBh1Seqe4rqF1+NuWmjhvtAni1JC5A
mail: billy@example.org
gecos: Billy User
# Create base group
dn: ou=groups,dc=example,dc=org
objectclass:organizationalunit
ou: groups
description: generic groups branch
# create mcsAdmin group (this already exists on minio and have a policy of s3::*)
dn: cn=mcsAdmin,ou=groups,dc=example,dc=org
objectClass: top
objectClass: posixGroup
gidNumber: 678
# Assing group to new user
dn: cn=mcsAdmin,ou=groups,dc=example,dc=org
changetype: modify
add: memberuid
memberuid: billy
EOF
$ docker cp billy.ldif my-openldap-container:/container/service/slapd/assets/test/billy.ldif
$ docker exec my-openldap-container ldapadd -x -D "cn=admin,dc=example,dc=org" -w admin -f /container/service/slapd/assets/test/billy.ldif -H ldap://localhost -ZZ
```
Query the ldap server to check the user billy was created correctly and got assigned to the mcsAdmin group, you should get a list
containing ldap users and groups.
```
$ docker exec my-openldap-container ldapsearch -x -H ldap://localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
```
Query the ldap server again, this time filtering only for the user `billy`, you should see only 1 record.
```
$ docker exec my-openldap-container ldapsearch -x -H ldap://localhost -b uid=billy,dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
```
### Change the password for user billy
Set the new password for `billy` to `minio123` and enter `admin` as the default `LDAP Password`
```
$ docker exec -it my-openldap-container /bin/bash
# ldappasswd -H ldap://localhost -x -D "cn=admin,dc=example,dc=org" -W -S "uid=billy,dc=example,dc=org"
New password:
Re-enter new password:
Enter LDAP Password:
```
### Add the mcsAdmin policy to user billy on MinIO
```
$ cat > mcsAdmin.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"admin:*"
],
"Effect": "Allow",
"Sid": ""
},
{
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
}
EOF
$ mc admin policy add myminio mcsAdmin mcsAdmin.json
$ mc admin policy set myminio mcsAdmin user=billy
```
## Run MinIO
```
export MINIO_ACCESS_KEY=minio
export MINIO_SECRET_KEY=minio123
export MINIO_IDENTITY_LDAP_SERVER_ADDR='localhost:389'
export MINIO_IDENTITY_LDAP_USERNAME_FORMAT='uid=%s,dc=example,dc=org'
export MINIO_IDENTITY_LDAP_USERNAME_SEARCH_FILTER='(|(objectclass=posixAccount)(uid=%s))'
export MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY=on
export MINIO_IDENTITY_LDAP_SERVER_INSECURE=on
./minio server ~/Data
```
## Run MCS
```
export MCS_ACCESS_KEY=minio
export MCS_SECRET_KEY=minio123
...
export MCS_LDAP_ENABLED=on
./mcs server
```

View File

@@ -1,8 +1,11 @@
FROM golang:1.14.1
FROM golang:1.13
RUN apt-get update -y && apt-get install -y ca-certificates
ADD go.mod /go/src/github.com/minio/mcs/go.mod
ADD go.sum /go/src/github.com/minio/mcs/go.sum
WORKDIR /go/src/github.com/minio/mcs/
# Get dependencies - will also be cached if we won't change mod/sum
RUN go mod download
@@ -11,7 +14,6 @@ WORKDIR /go/src/github.com/minio/mcs/
ENV CGO_ENABLED=0
RUN apt-get update -y && apt-get install -y ca-certificates
RUN go build -ldflags "-w -s" -a -o mcs ./cmd/mcs
FROM scratch

View File

@@ -1,23 +1,64 @@
PWD := $(shell pwd)
GOPATH := $(shell go env GOPATH)
# Sets the build version based on the output of the following command, if we are building for a tag, that's the build else it uses the current git branch as the build
BUILD_VERSION:=$(shell git describe --exact-match --tags $(git log -n1 --pretty='%h') 2>/dev/null || git rev-parse --abbrev-ref HEAD 2>/dev/null)
BUILD_TIME:=$(shell date 2>/dev/null)
TAG ?= "minio/m3:$(VERSION)-dev"
default: mcs
.PHONY: mcs
mcs:
@echo "Building mcs binary to './mcs'"
@(CGO_ENABLED=0 go build --tags=kqueue --ldflags "-s -w" -o mcs ./cmd/mcs)
@(GO111MODULE=on CGO_ENABLED=0 go build -trimpath --tags=kqueue --ldflags "-s -w" -o mcs ./cmd/mcs)
k8sdev:
@docker build -t $(TAG) --build-arg build_version=$(BUILD_VERSION) --build-arg build_time='$(BUILD_TIME)' .
@kind load docker-image $(TAG)
@echo "Done, now restart your mcs deployment"
getdeps:
@mkdir -p ${GOPATH}/bin
@which golangci-lint 1>/dev/null || (echo "Installing golangci-lint" && curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.27.0)
verifiers: getdeps fmt lint
fmt:
@echo "Running $@ check"
@GO111MODULE=on gofmt -d cmd/
@GO111MODULE=on gofmt -d pkg/
lint:
@echo "Running $@ check"
@GO111MODULE=on ${GOPATH}/bin/golangci-lint cache clean
@GO111MODULE=on ${GOPATH}/bin/golangci-lint run --timeout=5m --config ./.golangci.yml
install: mcs
@echo "Installing mcs binary to '$(GOPATH)/bin/mcs'"
@mkdir -p $(GOPATH)/bin && cp -f $(PWD)/mcs $(GOPATH)/bin/mcs
@echo "Installation successful. To learn more, try \"mcs --help\"."
swagger-gen:
@echo "Generating swagger server code from yaml"
@rm -rf models
@rm -rf restapi/operations
@swagger generate server -A mcs --main-package=mcs --exclude-main -P models.Principal -f ./swagger.yml -r NOTICE
build:
assets:
@(cd portal-ui; yarn install; make build-static; cd ..)
@(CGO_ENABLED=0 go build --tags kqueue --ldflags "-s -w" -o mcs ./cmd/mcs)
test:
@(go test ./restapi -v)
@(GO111MODULE=on go test -race -v github.com/minio/mcs/restapi/...)
@(GO111MODULE=on go test -race -v github.com/minio/mcs/pkg/...)
coverage:
@(go test ./restapi -v -coverprofile=coverage.out && go tool cover -html=coverage.out && open coverage.html)
@(GO111MODULE=on go test -v -coverprofile=coverage.out github.com/minio/mcs/restapi/... && go tool cover -html=coverage.out && open coverage.html)
clean:
@echo "Cleaning up all the generated files"
@find . -name '*.test' | xargs rm -fv
@find . -name '*~' | xargs rm -fv
@rm -vf mcs
docker:
@docker build -t $(TAG) --build-arg build_version=$(BUILD_VERSION) --build-arg build_time='$(BUILD_TIME)' .

143
README.md
View File

@@ -1,6 +1,11 @@
# MCS Minio Console Service
# Minio Console Server
This is a REST portal server created using [go-swagger](https://github.com/go-swagger/go-swagger)
A graphical user interface for [MinIO](https://github.com/minio/minio)
| Dashboard | Adding A User |
| ------------- | ------------- |
| ![Dashboard](images/pic1.png) | ![Dashboard](images/pic2.png) |
## Setup
@@ -14,31 +19,30 @@ $ mc admin user add myminio mcs YOURMCSSECRET
$ set -o history
```
2. Create a policy for `mcs`
2. Create a policy for `mcs` with access to everything (for testing and debugging)
```
$ cat > mcsAdmin.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"admin:*"
],
"Effect": "Allow",
"Sid": ""
},
{
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:*"
],
"Effect": "Allow",
"Sid": ""
},
{
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
}
EOF
$ mc admin policy add myminio mcsAdmin mcsAdmin.json
@@ -50,44 +54,77 @@ $ mc admin policy add myminio mcsAdmin mcsAdmin.json
$ mc admin policy set myminio mcsAdmin user=mcs
```
### Note
Additionally, you can create policies to limit the privileges for `mcs` users, for example, if you want the user to only have access to dashboard, buckets, notifications and watch page, the policy should look like this:
```
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:ServerInfo"
],
"Effect": "Allow",
"Sid": ""
},
{
"Action": [
"s3:ListenBucketNotification",
"s3:PutBucketNotification",
"s3:GetBucketNotification",
"s3:ListMultipartUploadParts",
"s3:ListBucketMultipartUploads",
"s3:ListBucket",
"s3:HeadBucket",
"s3:GetObject",
"s3:GetBucketLocation",
"s3:AbortMultipartUpload",
"s3:CreateBucket",
"s3:PutObject",
"s3:DeleteObject",
"s3:DeleteBucket",
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketPolicy"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
}
```
## Run MCS server
To run the server:
```
export MCS_HMAC_JWT_SECRET=YOURJWTSIGNINGSECRET
#required to encrypt jwet payload
export MCS_PBKDF_PASSPHRASE=SECRET
#required to encrypt jwet payload
export MCS_PBKDF_SALT=SECRET
export MCS_ACCESS_KEY=mcs
export MCS_SECRET_KEY=YOURMCSSECRET
export MCS_MINIO_SERVER=http://localhost:9000
./mcs
./mcs server
```
## Connect MCS to a Minio using TLS and a self-signed certificate
```
...
export MCS_MINIO_SERVER_TLS_SKIP_VERIFICATION=on
export MCS_MINIO_SERVER=https://localhost:9000
./mcs server
```
You can verify that the apis work by doing the request on `localhost:9090/api/v1/...`
# Development
The API handlers are created using a YAML definition located in `swagger.YAML`.
To add new api, the YAML file needs to be updated with all the desired apis using the [Swagger Basic Structure](https://swagger.io/docs/specification/2-0/basic-structure/), this includes paths, parameters, definitions, tags, etc.
## Generate server from YAML
Once the YAML file is ready we can autogenerate the code needed for the new api by just running:
Validate it:
```
swagger validate ./swagger.yml
```
Update server code:
```
make swagger-gen
```
This will update all the necessary code.
`./restapi/configure_mcs.go` is a file that contains the handlers to be used by the application, here is the only place where we need to update our code to support the new apis. This file is not affected when running the swagger generator and it is safe to edit.
## Unit Tests
`./restapi/handlers_test.go` needs to be updated with the proper tests for the new api.
To run tests:
```
go test ./restapi
```
# Contribute to mcs Project
Please follow mcs [Contributor's Guide](https://github.com/minio/mcs/blob/master/CONTRIBUTING.md)

41
SECURITY.md Normal file
View File

@@ -0,0 +1,41 @@
# Security Policy
## Supported Versions
We always provide security updates for the [latest release](https://github.com/minio/mcs/releases/latest).
Whenever there is a security update you just need to upgrade to the latest version.
## Reporting a Vulnerability
All security bugs in [minio/mcs](https://github,com/minio/mcs) (or other minio/* repositories)
should be reported by email to security@min.io. Your email will be acknowledged within 48 hours,
and you'll receive a more detailed response to your email within 72 hours indicating the next steps
in handling your report.
Please, provide a detailed explanation of the issue. In particular, outline the type of the security
issue (DoS, authentication bypass, information disclose, ...) and the assumptions you're making (e.g. do
you need access credentials for a successful exploit).
If you have not received a reply to your email within 48 hours or you have not heard from the security team
for the past five days please contact the security team directly:
- Primary security coordinator: lenin@min.io
- Secondary coordinator: daniel@min.io, cesar@min.io
- If you receive no response: dev@min.io
### Disclosure Process
MinIO uses the following disclosure process:
1. Once the security report is received one member of the security team tries to verify and reproduce
the issue and determines the impact it has.
2. A member of the security team will respond and either confirm or reject the security report.
If the report is rejected the response explains why.
3. Code is audited to find any potential similar problems.
4. Fixes are prepared for the latest release.
5. On the date that the fixes are applied a security advisory will be published on https://blog.min.io.
Please inform us in your report email whether MinIO should mention your contribution w.r.t. fixing
the security issue. By default MinIO will **not** publish this information to protect your privacy.
This process can take some time, especially when coordination is required with maintainers of other projects.
Every effort will be made to handle the bug in as timely a manner as possible, however it's important that we
follow the process described above to ensure that disclosures are handled consistently.

65
cluster/cluster.go Normal file
View File

@@ -0,0 +1,65 @@
// This file is part of MinIO Kubernetes Cloud
// Copyright (c) 2019 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 <http://www.gnu.org/licenses/>.
package cluster
import (
operator "github.com/minio/minio-operator/pkg/client/clientset/versioned"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
certutil "k8s.io/client-go/util/cert"
)
// getTLSClientConfig will return the right TLS configuration for the K8S client based on the configured TLS certificate
func getTLSClientConfig() rest.TLSClientConfig {
var defaultRootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
var customRootCAFile = getK8sAPIServerTLSRootCA()
tlsClientConfig := rest.TLSClientConfig{}
// if console is running inside k8s by default he will have access to the CA Cert from the k8s local authority
if _, err := certutil.NewPool(defaultRootCAFile); err == nil {
tlsClientConfig.CAFile = defaultRootCAFile
}
// if the user explicitly define a custom CA certificate, instead, we will use that
if customRootCAFile != "" {
if _, err := certutil.NewPool(customRootCAFile); err == nil {
tlsClientConfig.CAFile = customRootCAFile
}
}
return tlsClientConfig
}
// This operation will run only once at console startup
var tlsClientConfig = getTLSClientConfig()
func GetK8sConfig(token string) *rest.Config {
config := &rest.Config{
Host: GetK8sAPIServer(),
TLSClientConfig: tlsClientConfig,
APIPath: "/",
BearerToken: token,
}
return config
}
// OperatorClient returns an operator client using GetK8sConfig for its config
func OperatorClient(token string) (*operator.Clientset, error) {
return operator.NewForConfig(GetK8sConfig(token))
}
// K8sClient returns kubernetes client using GetK8sConfig for its config
func K8sClient(token string) (*kubernetes.Clientset, error) {
return kubernetes.NewForConfig(GetK8sConfig(token))
}

168
cluster/config.go Normal file
View File

@@ -0,0 +1,168 @@
// This file is part of MinIO Kubernetes Cloud
// Copyright (c) 2019 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 <http://www.gnu.org/licenses/>.
package cluster
import (
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"regexp"
"strings"
"time"
"github.com/minio/minio/pkg/env"
)
var (
errCantDetermineMinIOImage = errors.New("can't determine MinIO Image")
errCantDetermineMCImage = errors.New("can't determine MC Image")
)
func GetK8sAPIServer() string {
// if console is running inside a k8s pod KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT will contain the k8s api server apiServerAddress
// if console is not running inside k8s by default will look for the k8s api server on localhost:8001 (kubectl proxy)
// NOTE: using kubectl proxy is for local development only, since every request send to localhost:8001 will bypass service account authentication
// more info here: https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#directly-accessing-the-rest-api
// you can override this using MCS_K8S_API_SERVER, ie use the k8s cluster from `kubectl config view`
host, port := env.Get("KUBERNETES_SERVICE_HOST", ""), env.Get("KUBERNETES_SERVICE_PORT", "")
apiServerAddress := "http://localhost:8001"
if host != "" && port != "" {
apiServerAddress = "https://" + net.JoinHostPort(host, port)
}
return env.Get(McsK8sAPIServer, apiServerAddress)
}
// If MCS_K8S_API_SERVER_TLS_ROOT_CA is true mcs will load the certificate into the
// http.client rootCAs pool, this is useful for testing an k8s ApiServer or when working with self-signed certificates
func getK8sAPIServerTLSRootCA() string {
return strings.TrimSpace(env.Get(McsK8SAPIServerTLSRootCA, ""))
}
// GetNsFromFile assumes console is running inside a k8s pod and extract the current namespace from the
// /var/run/secrets/kubernetes.io/serviceaccount/namespace file
func GetNsFromFile() string {
dat, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
return "default"
}
return string(dat)
}
// This operation will run only once at console startup
var namespace = GetNsFromFile()
// Returns the namespace in which the controller is installed
func GetNs() string {
return env.Get(McsNamespace, namespace)
}
// getLatestMinIOImage returns the latest docker image for MinIO if found on the internet
func getLatestMinIOImage(client HTTPClientI) (*string, error) {
resp, err := client.Get("https://dl.min.io/server/minio/release/linux-amd64/")
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var re = regexp.MustCompile(`(?m)\.\/minio\.(RELEASE.*?Z)"`)
// look for a single match
matches := re.FindAllStringSubmatch(string(body), 1)
for i := range matches {
release := matches[i][1]
dockerImage := fmt.Sprintf("minio/minio:%s", release)
return &dockerImage, nil
}
return nil, errCantDetermineMinIOImage
}
var latestMinIOImage, errLatestMinIOImage = getLatestMinIOImage(
&HTTPClient{
Client: &http.Client{
Timeout: 4 * time.Second,
},
})
// GetMinioImage returns the image URL to be used when deploying a MinIO instance, if there is
// a preferred image to be used (configured via ENVIRONMENT VARIABLES) GetMinioImage will return that
// if not, GetMinioImage will try to obtain the image URL for the latest version of MinIO and return that
func GetMinioImage() (*string, error) {
image := strings.TrimSpace(env.Get(McsMinioImage, ""))
// if there is a preferred image configured by the user we'll always return that
if image != "" {
return &image, nil
}
if errLatestMinIOImage != nil {
return nil, errLatestMinIOImage
}
return latestMinIOImage, nil
}
// GetLatestMinioImage returns the latest image URL on minio repository
func GetLatestMinioImage(client HTTPClientI) (*string, error) {
latestMinIOImage, err := getLatestMinIOImage(client)
if err != nil {
return nil, err
}
return latestMinIOImage, nil
}
// getLatestMCImage returns the latest docker image for MC if found on the internet
func getLatestMCImage() (*string, error) {
// Create an http client with a 4 second timeout
client := http.Client{
Timeout: 4 * time.Second,
}
resp, err := client.Get("https://dl.min.io/client/mc/release/linux-amd64/")
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var re = regexp.MustCompile(`(?m)\.\/mc\.(RELEASE.*?Z)"`)
// look for a single match
matches := re.FindAllStringSubmatch(string(body), 1)
for i := range matches {
release := matches[i][1]
dockerImage := fmt.Sprintf("minio/mc:%s", release)
return &dockerImage, nil
}
return nil, errCantDetermineMCImage
}
var latestMCImage, errLatestMCImage = getLatestMCImage()
func GetMCImage() (*string, error) {
image := strings.TrimSpace(env.Get(McsMCImage, ""))
// if there is a preferred image configured by the user we'll always return that
if image != "" {
return &image, nil
}
if errLatestMCImage != nil {
return nil, errLatestMCImage
}
return latestMCImage, nil
}

25
cluster/const.go Normal file
View File

@@ -0,0 +1,25 @@
// This file is part of MinIO Kubernetes Cloud
// Copyright (c) 2019 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 <http://www.gnu.org/licenses/>.
package cluster
const (
McsK8sAPIServer = "MCS_K8S_API_SERVER"
McsK8SAPIServerTLSRootCA = "MCS_K8S_API_SERVER_TLS_ROOT_CA"
McsMinioImage = "MCS_MINIO_IMAGE"
McsMCImage = "MCS_MC_IMAGE"
McsNamespace = "MCS_NAMESPACE"
)

40
cluster/http_client.go Normal file
View File

@@ -0,0 +1,40 @@
// This file is part of MinIO Kubernetes Cloud
// 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 <http://www.gnu.org/licenses/>.
package cluster
import (
"net/http"
)
// HTTPClientI interface with all functions to be implemented
// by mock when testing, it should include all HttpClient respective api calls
// that are used within this project.
type HTTPClientI interface {
Get(url string) (resp *http.Response, err error)
}
// HTTPClient Interface implementation
//
// Define the structure of a http client and define the functions that are actually used
type HTTPClient struct {
Client *http.Client
}
// Get implements http.Client.Get()
func (c *HTTPClient) Get(url string) (resp *http.Response, err error) {
return c.Client.Get(url)
}

View File

@@ -21,8 +21,9 @@ import (
"os"
"path/filepath"
"sort"
"time"
"github.com/minio/m3/mcs/pkg"
"github.com/minio/mcs/pkg"
"github.com/minio/minio/pkg/console"
"github.com/minio/minio/pkg/trie"
@@ -31,7 +32,7 @@ import (
"github.com/minio/cli"
)
// Help template for m3.
// Help template for mcs.
var mcsHelpTemplate = `NAME:
{{.Name}} - {{.Usage}}
@@ -53,14 +54,13 @@ VERSION:
var appCmds = []cli.Command{
serverCmd,
versionCmd,
}
func newApp(name string) *cli.App {
// Collection of m3 commands currently supported are.
commands := []cli.Command{}
// Collection of mcs commands currently supported are.
var commands []cli.Command
// Collection of m3 commands currently supported in a trie tree.
// Collection of mcs commands currently supported in a trie tree.
commandsTree := trie.NewTrie()
// registerCommand registers a cli command.
@@ -104,10 +104,12 @@ func newApp(name string) *cli.App {
app := cli.NewApp()
app.Name = name
app.Version = pkg.Version
app.Version = pkg.Version + " - " + pkg.ShortCommitID
app.Author = "MinIO, Inc."
app.Usage = "mcs COMMAND"
app.Usage = "MinIO Console Server"
app.Description = `MinIO Console Server`
app.Copyright = "(c) 2020 MinIO, Inc."
app.Compiled, _ = time.Parse(time.RFC3339, pkg.ReleaseTime)
app.Commands = commands
app.HideHelpCommand = true // Hide `help, h` command, we already have `minio --help`.
app.CustomAppHelpTemplate = mcsHelpTemplate

View File

@@ -17,15 +17,15 @@
package main
import (
"flag"
"fmt"
"log"
"os"
"github.com/go-openapi/loads"
"github.com/jessevdk/go-flags"
"github.com/minio/cli"
"github.com/minio/m3/mcs/restapi"
"github.com/minio/m3/mcs/restapi/operations"
"github.com/minio/mcs/restapi"
"github.com/minio/mcs/restapi/operations"
)
// starts the server
@@ -35,10 +35,35 @@ var serverCmd = cli.Command{
Usage: "starts mcs server",
Action: startServer,
Flags: []cli.Flag{
cli.StringFlag{
Name: "host",
Value: restapi.GetHostname(),
Usage: "HTTP server hostname",
},
cli.IntFlag{
Name: "port",
Value: 9090,
Usage: "Server port",
Value: restapi.GetPort(),
Usage: "HTTP Server port",
},
cli.StringFlag{
Name: "tls-host",
Value: restapi.GetSSLHostname(),
Usage: "HTTPS server hostname",
},
cli.IntFlag{
Name: "tls-port",
Value: restapi.GetSSLPort(),
Usage: "HTTPS server port",
},
cli.StringFlag{
Name: "tls-certificate",
Value: "",
Usage: "filename of public cert",
},
cli.StringFlag{
Name: "tls-key",
Value: "",
Usage: "filename of private key",
},
},
}
@@ -74,11 +99,32 @@ func startServer(ctx *cli.Context) error {
}
os.Exit(code)
}
// Parse flags
flag.Parse()
server.ConfigureAPI()
server.Host = ctx.String("host")
server.Port = ctx.Int("port")
restapi.Hostname = ctx.String("host")
restapi.Port = fmt.Sprintf("%v", ctx.Int("port"))
tlsCertificatePath := ctx.String("tls-certificate")
tlsCertificateKeyPath := ctx.String("tls-key")
if tlsCertificatePath != "" && tlsCertificateKeyPath != "" {
server.TLSCertificate = flags.Filename(tlsCertificatePath)
server.TLSCertificateKey = flags.Filename(tlsCertificateKeyPath)
// If TLS certificates are provided enforce the HTTPS schema, meaning mcs will redirect
// plain HTTP connections to HTTPS server
server.EnabledListeners = []string{"http", "https"}
server.TLSPort = ctx.Int("tls-port")
server.TLSHost = ctx.String("tls-host")
// Need to store tls-port, tls-host un config variables so secure.middleware can read from there
restapi.TLSPort = fmt.Sprintf("%v", ctx.Int("tls-port"))
restapi.TLSHostname = ctx.String("tls-host")
restapi.TLSRedirect = "on"
}
server.ConfigureAPI()
if err := server.Serve(); err != nil {
log.Fatalln(err)
}

80
code_of_conduct.md Normal file
View File

@@ -0,0 +1,80 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior, in compliance with the
licensing terms applying to the Project developments.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful. However, these actions shall respect the
licensing terms of the Project Developments that will always supersede such
Code of Conduct.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at dev@min.io. The project team
will review and investigate all complaints, and will respond in a way that it deems
appropriate to the circumstances. The project team is obligated to maintain
confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
This version includes a clarification to ensure that the code of conduct is in
compliance with the free software licensing terms of the project.
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

39
docs/mcs_operator_mode.md Normal file
View File

@@ -0,0 +1,39 @@
# Running MCS in Operator mode
`MCS` will authenticate against `Kubernetes`using bearer tokens via HTTP `Authorization` header. The user will provide this token once
in the login form, MCS will validate it against Kubernetes (list apis) and if valid will generate and return a new MCS sessions
with encrypted claims (the user Service account token will be inside the JWT in the data field)
# Kubernetes
The provided `JWT token` corresponds to the `Kubernetes service account` that `MCS` will use to run tasks on behalf of the
user, ie: list, create, edit, delete tenants, storage class, etc.
# Development
If console is running inside a k8s pod `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` will contain the k8s api server apiServerAddress
if console is not running inside k8s by default will look for the k8s api server on `localhost:8001` (kubectl proxy)
If you are running mcs in your local environment and wish to make request to `Kubernetes` you can set `MCS_K8S_API_SERVER`, if
the environment variable is not present by default `MCS` will use `"http://localhost:8001"`, additionally you will need to set the
`MCS_OPERATOR_MODE=on` variable to make MCS display the Operator UI.
NOTE: using `kubectl` proxy is for local development only, since every request send to localhost:8001 will bypass service account authentication
more info here: https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#directly-accessing-the-rest-api
you can override this using `MCS_K8S_API_SERVER`, ie use the k8s cluster from `kubectl config view`
## Extract the Service account token and use it with MCS
For local development you can use the jwt associated to the `m3-sa` service account, you can get the token running
the following command in your terminal:
```
kubectl get secret $(kubectl get serviceaccount mcs-sa -o jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" | base64 --decode
```
Then run the mcs server
```
MCS_OPERATOR_MODE=on ./mcs server
```

37
go.mod
View File

@@ -1,21 +1,34 @@
module github.com/minio/m3/mcs
module github.com/minio/mcs
go 1.14
go 1.13
require (
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/elazarl/go-bindata-assetfs v1.0.0
github.com/go-openapi/errors v0.19.4
github.com/go-openapi/errors v0.19.6
github.com/go-openapi/loads v0.19.5
github.com/go-openapi/runtime v0.19.12
github.com/go-openapi/spec v0.19.7
github.com/go-openapi/runtime v0.19.19
github.com/go-openapi/spec v0.19.8
github.com/go-openapi/strfmt v0.19.5
github.com/go-openapi/swag v0.19.8
github.com/go-openapi/validate v0.19.7
github.com/go-openapi/swag v0.19.9
github.com/go-openapi/validate v0.19.10
github.com/gorilla/websocket v1.4.2
github.com/jessevdk/go-flags v1.4.0
github.com/json-iterator/go v1.1.9
github.com/minio/cli v1.22.0
github.com/minio/mc v0.0.0-20200403024131-4d36c1f8b856
github.com/minio/minio v0.0.0-20200327214830-6f992134a25f
github.com/minio/minio-go/v6 v6.0.51-0.20200401083717-eadbcae2a0e6
github.com/stretchr/testify v1.5.1
golang.org/x/net v0.0.0-20200301022130-244492dfa37a
github.com/minio/mc v0.0.0-20200515235434-3b479cf92ed6
github.com/minio/minio v0.0.0-20200603201854-5686a7e27319
github.com/minio/minio-go/v6 v6.0.56
github.com/minio/minio-operator v0.0.0-20200520220606-60eca6e7beab
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/satori/go.uuid v1.2.0
github.com/stretchr/testify v1.6.1
github.com/unrolled/secure v1.0.7
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
golang.org/x/net v0.0.0-20200602114024-627f9648deb9
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
k8s.io/api v0.18.0
k8s.io/apimachinery v0.18.0
k8s.io/client-go v0.18.0
)

317
go.sum
View File

@@ -1,7 +1,9 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
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,45 +11,64 @@ 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/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0 h1:q2gDruN08/guU9vAjuPWff0+QIrpH6ediguzdAzXAUU=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
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=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
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=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alecthomas/participle v0.2.1 h1:4AVLj1viSGa4LG5HDXKXrm5xRx19SB/rS/skPQB1Grw=
github.com/alecthomas/participle v0.2.1/go.mod h1:SW6HZGeZgSIpcUWX3fXpfZhuaWHnmoD5KCVaqSaNTkk=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 h1:nWDRPCyCltiTsANwC/n3QZH7Vww33Npq9MKqlwRzI/c=
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=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/aws/aws-sdk-go v1.20.21/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2 h1:M+TYzBcNIRyzPRg66ndEqUMd7oWDmhvdQmaPC6EZNwM=
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2/go.mod h1:RDu/qcrnpEdJC/p8tx34+YBFqqX71lB7dOX9QE+ZC4M=
github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
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 v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
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=
github.com/cheggaaa/pb v1.0.28 h1:kWGpdAcSp3MxMU9CCHOwz/8V0kCHN4+9yQm2MzWuI98=
@@ -55,28 +76,37 @@ github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXH
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY=
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
github.com/colinmarc/hdfs/v2 v2.1.1 h1:x0hw/m+o3UE20Scso/KCkvYNc9Di39TBlCfGMkJ1/a0=
github.com/colinmarc/hdfs/v2 v2.1.1/go.mod h1:M3x+k8UKKmxtFu++uAZ0OtDU8jR3jnaZIAc6yK4Ue0c=
github.com/coredns/coredns v1.4.0 h1:RubBkYmkByUqZWWkjRHvNLnUHgkRVqAWgSMmRFvpE1A=
github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0=
github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY=
github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.12+incompatible h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ=
github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/djherbis/atime v1.0.0 h1:ySLvBAM0EvOGaX7TI4dAM5lWj+RdJUCKtGSEHN8SGBg=
github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
@@ -90,22 +120,35 @@ github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
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/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-ldap/ldap v3.0.2+incompatible h1:kD5HQcAzlQ7yrhfn+h+MSABeAy/jAJhvIJ/QDllP44g=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
@@ -120,13 +163,15 @@ github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQH
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/errors v0.19.4 h1:fSGwO1tSYHFu70NKaWJt5Qh0qoBRtCm/mXS1yhf+0W0=
github.com/go-openapi/errors v0.19.4/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/errors v0.19.6 h1:xZMThgv5SQ7SMbWtKFkCf9bBdvR2iEyw9k3zGZONuys=
github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@@ -137,21 +182,22 @@ github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI=
github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=
github.com/go-openapi/loads v0.19.5 h1:jZVYWawIQiA1NBnHla28ktg6hrcfTHsCE+3QLVRBIls=
github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY=
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
github.com/go-openapi/runtime v0.19.12 h1:5lQlCr1HL0ZVRPL+0PHKhRpMCSPMV2qF842rhQx8CYY=
github.com/go-openapi/runtime v0.19.12/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
github.com/go-openapi/runtime v0.19.19 h1:PCaQSqG0HiCgpekchPrHO9AEc5ZUaAclOUp9T3RSKoQ=
github.com/go-openapi/runtime v0.19.19/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/spec v0.19.7 h1:0xWSeMd35y5avQAThZR2PkEuqSosoS5t6gDH4L8n11M=
github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/spec v0.19.8 h1:qAdZLh1r6QF/hI/gTq+TJTvsQUodZsM7KLqkAJdiJNg=
github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
@@ -160,18 +206,19 @@ github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6
github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
github.com/go-openapi/strfmt v0.19.5 h1:0utjKrw+BAh8s57XE9Xz8DUBsVvPmRUB6styvl9wWIM=
github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.8 h1:vfK6jLhs7OI4tAXkvkooviaE1JEPcw3mutyegLHHjmk=
github.com/go-openapi/swag v0.19.8/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.9 h1:1IxuqvBUU3S2Bi4YC7tlP9SJF1gVpCvqN0T2Qof4azE=
github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
github.com/go-openapi/validate v0.19.7 h1:fR4tP2xc+25pdo5Qvv4v6g+5QKFgNg8nrifTE7V8ibA=
github.com/go-openapi/validate v0.19.7/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-openapi/validate v0.19.10 h1:tG3SZ5DC5KF4cyt7nqLVcQXGj5A7mpaYkAcNPlDK+Yk=
github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
@@ -204,36 +251,51 @@ github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY9
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw=
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190328170749-bb2674552d8f h1:4Gslotqbs16iAg+1KR/XdabIfq8TlAWHdwS5QJFksLc=
github.com/gopherjs/gopherjs v0.0.0-20190328170749-bb2674552d8f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -245,6 +307,9 @@ github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk=
github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg=
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
@@ -262,8 +327,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=
@@ -275,6 +343,7 @@ github.com/hashicorp/go-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+0
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-uuid v0.0.0-20180228145832-27454136f036/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
@@ -284,6 +353,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=
@@ -292,9 +362,15 @@ github.com/hashicorp/vault/sdk v0.1.13 h1:mOEPeOhT7jl0J4AMl1E705+BcmeRs1VmKNb9F0
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jcmturner/gofork v0.0.0-20180107083740-2aebee971930/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03 h1:FUwcHNlEqkqLjLBdCp5PRlCFijNjvcYANOZXzCfXwCM=
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
@@ -303,6 +379,8 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@@ -322,12 +400,16 @@ github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eT
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v1.2.2 h1:1xAgYebNnsb9LKCdLOvFWtAxGU/33mjJtyOVbmUa0Us=
github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.4 h1:EBfaK0SWSwk+fgk6efYFWdzl8MwRWoOO1gkmiaTXPW4=
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM=
github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/klauspost/readahead v1.3.1 h1:QqXNYvm+VvqYcbrRT4LojUciM0XrznFRIDrbHiJtu/0=
github.com/klauspost/readahead v1.3.1/go.mod h1:AH9juHzNH7xqdqFHrMRSHeH2Ps+vFf+kblDqzPFiLJg=
github.com/klauspost/reedsolomon v1.9.3 h1:N/VzgeMfHmLc+KHMD1UL/tNkfXAt8FnUqlgXGIduwAY=
github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/klauspost/reedsolomon v1.9.7 h1:+azeqnT4iNG9UEcWC+7utJ4xXQ9S8pSlkZor0DOArEQ=
github.com/klauspost/reedsolomon v1.9.7/go.mod h1:+8WD025Xpby8/kG5h/HDPIFhiiuGEtZOKw+5Y4drAD8=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -338,16 +420,18 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kurin/blazer v0.5.4-0.20190613185654-cf2f27cc0be3 h1:1sl2HmNtqGnDuydLgCJwZIpDLGqZOdwOkcY8WtUl8Cw=
github.com/kurin/blazer v0.5.4-0.20190613185654-cf2f27cc0be3/go.mod h1:4FCXMUWo9DllR2Do4TtBd377ezyAJ51vB5uTBjt0pGU=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kurin/blazer v0.5.4-0.20200327014341-8f90a40f8af7 h1:smZXPopqRVVywwzou4WYWvUbJvSAzIDFizfWElpmAqY=
github.com/kurin/blazer v0.5.4-0.20200327014341-8f90a40f8af7/go.mod h1:4FCXMUWo9DllR2Do4TtBd377ezyAJ51vB5uTBjt0pGU=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
@@ -383,17 +467,23 @@ github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2
github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc=
github.com/minio/lsync v1.0.1 h1:AVvILxA976xc27hstd1oR+X9PQG0sPSom1MNb1ImfUs=
github.com/minio/lsync v1.0.1/go.mod h1:tCFzfo0dlvdGl70IT4IAK/5Wtgb0/BrTmo/jE8pArKA=
github.com/minio/mc v0.0.0-20200403024131-4d36c1f8b856 h1:4uIc5fw4tVr5glh2Mc8GFuiY04pTGEhmihPxJPUvCoU=
github.com/minio/mc v0.0.0-20200403024131-4d36c1f8b856/go.mod h1:IDy4dA4aFY6zFFNkYgdUztl0jcYuev/Ubg3NadoaMKc=
github.com/minio/minio v0.0.0-20200327214830-6f992134a25f h1:RoOBi0vhXkZqe2b6RTROOsVJUwMqLMoet9r7eL01euo=
github.com/minio/minio v0.0.0-20200327214830-6f992134a25f/go.mod h1:BzbIyKUJPp+4f03i2XF7+GsijXnxMakUe5x+lm2WNc8=
github.com/minio/minio-go/v6 v6.0.45/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
github.com/minio/minio-go/v6 v6.0.51-0.20200319192131-097caa7760c7 h1:WQmYVUDRGdcEWhJeb42/Fn1IO7SBLem173DTE4+jp/E=
github.com/minio/minio-go/v6 v6.0.51-0.20200319192131-097caa7760c7/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
github.com/minio/minio-go/v6 v6.0.51-0.20200401083717-eadbcae2a0e6 h1:7JhqKjmt1Tv6co7eP/40/xtDLrzzWu1UwUNwQzSvcb0=
github.com/minio/minio-go/v6 v6.0.51-0.20200401083717-eadbcae2a0e6/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
github.com/minio/parquet-go v0.0.0-20200125064549-a1e49702e174 h1:WYFHZIJ5LTWd4C3CW26jguaBLLDdX7l1/Xa3QSKGkIc=
github.com/minio/parquet-go v0.0.0-20200125064549-a1e49702e174/go.mod h1:PXYM9yI2l0YPmxHUXe6mFTmkQcyaVasDshAPTbGpDoo=
github.com/minio/mc v0.0.0-20200515235434-3b479cf92ed6 h1:2SrKe2vLDLwvnYkYrJelrzyGW8t/8HCbr9yDsw+8XSI=
github.com/minio/mc v0.0.0-20200515235434-3b479cf92ed6/go.mod h1:U3Jgk0bcSjn+QPUMisrS6nxCWOoQ6rYWSvLCB30apuU=
github.com/minio/minio v0.0.0-20200421050159-282c9f790a03/go.mod h1:zBua5AiljGs1Irdl2XEyiJjvZVCVDIG8gjozzRBcVlw=
github.com/minio/minio v0.0.0-20200501124117-09571d03a531/go.mod h1:Vhlqz7Se0EgpgFiVxpvzF4Zz/h2LMx+EPKH96Aera5U=
github.com/minio/minio v0.0.0-20200603201854-5686a7e27319 h1:Vh7ATrN/BDjUx9XBKg5fpqSn2LPV/9BKKdldu31+2HY=
github.com/minio/minio v0.0.0-20200603201854-5686a7e27319/go.mod h1:hW3OqYRO05rdeeuHHTif+B7WYxtDB3/hZb7eKfHXy1Y=
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.55-0.20200424204115-7506d2996b22/go.mod h1:KQMM+/44DSlSGSQWSfRrAZ12FVMmpWNuX37i2AX0jfI=
github.com/minio/minio-go/v6 v6.0.56-0.20200502013257-a81c8c13cc3f h1:ifHrI8+exqLi5RztIWWKS5k+Wu+W7DJisVXwNaCH2zs=
github.com/minio/minio-go/v6 v6.0.56-0.20200502013257-a81c8c13cc3f/go.mod h1:KQMM+/44DSlSGSQWSfRrAZ12FVMmpWNuX37i2AX0jfI=
github.com/minio/minio-go/v6 v6.0.56 h1:H4+v6UFV1V7VkEf1HjL15W9OvTL1Gy8EbMmjQZHqEbg=
github.com/minio/minio-go/v6 v6.0.56/go.mod h1:KQMM+/44DSlSGSQWSfRrAZ12FVMmpWNuX37i2AX0jfI=
github.com/minio/minio-operator v0.0.0-20200520220606-60eca6e7beab h1:gEsXYeVtpPEJjP01tcS83utSO/kohkE5LRW3+4yKxEA=
github.com/minio/minio-operator v0.0.0-20200520220606-60eca6e7beab/go.mod h1:wtZCfrTLhFQ8K8vjOK4k9daN//AVNKVSlNO87KRgWOw=
github.com/minio/parquet-go v0.0.0-20200414234858-838cfa8aae61 h1:pUSI/WKPdd77gcuoJkSzhJ4wdS8OMDOsOu99MtpXEQA=
github.com/minio/parquet-go v0.0.0-20200414234858-838cfa8aae61/go.mod h1:4trzEJ7N1nBTd5Tt7OCZT5SEin+WiAXpdJ/WgPkESA8=
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/minio/simdjson-go v0.1.5-0.20200303142138-b17fe061ea37 h1:pDeao6M5AEd8hwTtGmE0pVKomlL56JFRa5SiXDZAuJE=
@@ -409,6 +499,8 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mmcloughlin/avo v0.0.0-20200303042253-6df701fe672f h1:4a8aNS/kCsM3TZnLO0jUzMAch5+XYh5Poe74nqatJcw=
github.com/mmcloughlin/avo v0.0.0-20200303042253-6df701fe672f/go.mod h1:L0u9qfRMLNBO97u6pPukRp6ncoQz0Q25W69fvtht3vA=
@@ -421,15 +513,23 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/montanaflynn/stats v0.5.0 h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk=
github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
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=
@@ -442,14 +542,26 @@ github.com/nats-io/stan.go v0.4.5 h1:lPZ9y1jVGiXcTaUc1SnEIWPYfh0avuEiHBePNJYgpPk
github.com/nats-io/stan.go v0.4.5/go.mod h1:Ji7mK6gRZJSH1nc3ZJH6vi7zn/QnZhpR9Arm4iuzsUQ=
github.com/ncw/directio v1.0.5 h1:JSUBhdjEvVaJvOoyPAbcW0fnd0tvRXD76wEfZ1KcQz4=
github.com/ncw/directio v1.0.5/go.mod h1:rX/pKEYkOXBGOggmcyJeJGloCkleSvphPx2eV3t6ROk=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
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=
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@@ -468,21 +580,31 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.2-0.20190702141536-6ffe496ea953 h1:oBvgW8IvwF278gJ3R4hH0gD3ZeJxjwBXVIScRR0dRc8=
github.com/posener/complete v1.2.2-0.20190702141536-6ffe496ea953/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20190704165056-9c2d0518ed81 h1:zQTtDd7fQiF9e80lbl+ShnD9/5NSq5r1EhcS8955ECg=
github.com/rcrowley/go-metrics v0.0.0-20190704165056-9c2d0518ed81/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@@ -497,10 +619,10 @@ github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/secure-io/sio-go v0.3.0 h1:QKGb6rGJeiExac9wSWxnWPYo8O8OFN7lxXQvHshX6vo=
github.com/secure-io/sio-go v0.3.0/go.mod h1:D3KmXgKETffyYxBdFRN+Hpd2WzhzqS0EQwT3XWsAcBU=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil v2.20.3-0.20200314133625-53cec6b37e6a+incompatible h1:YiKUe2ZOmfpDBH4OSyxwkx/mjNqHHnNhOtZ2mPyRme8=
github.com/shirou/gopsutil v2.20.3-0.20200314133625-53cec6b37e6a+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -508,28 +630,40 @@ github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e h1:jrZSSgPUDtBeJbGXqgGUeupQH8I+ZvGXfhpIahye2Bc=
github.com/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e/go.mod h1:d8hQseuYt4rJoOo21lFzYJdhMjmDqLY++ayArbgYjWI=
github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q=
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 h1:hBSHahWMEgzwRyS6dRpxY0XyjZsHyQ61s084wo5PJe0=
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/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 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRNFYlvKwSr5zff2v+uPHaffZ6/M4k=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/gjson v1.3.5 h1:2oW9FBNu8qt9jy5URgrzsVx/T/KSn3qn/smJQ0crlDQ=
github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
@@ -549,9 +683,14 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/unrolled/secure v1.0.7 h1:BcQHp3iKZyZCKj5gRqwQG+5urnGBF00wGgoPPwtheVQ=
github.com/unrolled/secure v1.0.7/go.mod h1:uGc1OcRF8gCVBA+ANksKmvM85Hka6SZtQIbrKc3sHS4=
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=
@@ -559,47 +698,70 @@ github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.3.0 h1:ew6uUIeJOo+qdUUv7LxFCUhtWmVv7ZV/Xuy4FAUsw2E=
go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
go.mongodb.org/mongo-driver v1.3.4 h1:zs/dKNwX0gYUtzwrN9lLiR15hCO0nDwQj5xXx+vjCdE=
go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.11.0 h1:gSmpCfs+R47a4yQPAI4xJ0IPDLTRGXskm6UelqNXpqE=
go.uber.org/zap v1.11.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f h1:kz4KIr+xcPUsI3VMoqWfPMvtnJ6MGfiVwsWSVzphMO4=
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 h1:Sy5bstxEqwwbYs6n0/pBuxKENqOeZUgD45Gp3Q3pqLg=
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -614,30 +776,40 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181021155630-eda9bb28ed51/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -649,8 +821,10 @@ golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200320181252-af34d8274f85 h1:fD99hd4ciR6T3oPhr2EkmuKe9oHixHx9Hj/hND89j3g=
golang.org/x/sys v0.0.0-20200320181252-af34d8274f85/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -661,9 +835,9 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZe
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -675,19 +849,32 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190914235951-31e00f45c22e h1:nOOVVcLC+/3MeovP40q5lCiWmP1Z1DaN8yn8ngU63hw=
golang.org/x/tools v0.0.0-20190914235951-31e00f45c22e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200428211428-0c9eba77bc32/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770 h1:M9Fif0OxNji8w+HvmhVQ8KJtiZOsjU9RgslJGhn95XE=
golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.5.0 h1:lj9SyhMzyoa38fgFF0oO2T6pjs5IzkLPKfVtxpyCRMM=
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw=
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190513181449-d00d292a067c/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
@@ -703,16 +890,23 @@ gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUy
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk=
gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/h2non/filetype.v1 v1.0.5 h1:CC1jjJjoEhNVbMhXYalmGBhOBK2V70Q1N850wt/98/Y=
gopkg.in/h2non/filetype.v1 v1.0.5/go.mod h1:M0yem4rwSX5lLVrkEuRRp2/NinFMD5vgJ4DlAhZcfNo=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.48.0 h1:URjZc+8ugRY5mL5uUeQH/a63JcHwdX9xZaWvmNWD7z8=
gopkg.in/ini.v1 v1.48.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.52.0 h1:j+Lt/M1oPPejkniCg1TkWE2J3Eh1oZTsHSXzMTzUXn4=
gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw=
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM=
@@ -721,6 +915,8 @@ gopkg.in/jcmturner/goidentity.v3 v3.0.0 h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXt
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
gopkg.in/jcmturner/gokrb5.v7 v7.2.3 h1:hHMV/yKPwMnJhPuPx7pH2Uw/3Qyf+thJYlisUc44010=
gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
gopkg.in/jcmturner/gokrb5.v7 v7.3.0 h1:0709Jtq/6QXEuWRfAm260XqlpcwL1vxtO1tUE2qK8Z4=
gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU=
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
gopkg.in/ldap.v3 v3.0.3 h1:YKRHW/2sIl05JsCtx/5ZuUueFuJyoj/6+DGXe3wp6ro=
@@ -730,6 +926,8 @@ gopkg.in/olivere/elastic.v5 v5.0.80/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0F
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -737,7 +935,38 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.18.0 h1:lwYk8Vt7rsVTwjRU6pzEsa9YNhThbmbocQlKvNBB4EQ=
k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
k8s.io/apimachinery v0.18.0 h1:fuPfYpk3cs1Okp/515pAf0dNhL66+8zk8RLbSX+EgAE=
k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
k8s.io/client-go v0.18.0 h1:yqKw4cTUQraZK3fcVCMeSa+lqKwcjZ5wtcOIPnxQno4=
k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c h1:/KUFqjjqAcY4Us6luF5RDNZ16KJtb49HfR3ZHB9qYXM=
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

31
hack/update-codegen.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/bash
#
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
go get -d k8s.io/code-generator/...
# Checkout code-generator to compatible version
#(cd $GOPATH/src/k8s.io/code-generator && git checkout origin/release-1.14 -B release-1.14)
REPOSITORY=github.com/minio/mcs
$GOPATH/src/k8s.io/code-generator/generate-groups.sh all \
$REPOSITORY/pkg/clientgen $REPOSITORY/pkg/apis networking.gke.io:v1beta2 \
--go-header-file $SCRIPT_ROOT/hack/header.go.txt

BIN
images/pic1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 KiB

BIN
images/pic2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 KiB

15
k8s/boilerplate.go.txt Normal file
View File

@@ -0,0 +1,15 @@
// 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 <http://www.gnu.org/licenses/>.

View File

@@ -0,0 +1,11 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# beginning of customizations
resources:
- mcs-service-account.yaml
- mcs-cluster-role.yaml
- mcs-cluster-role-binding.yaml
- mcs-configmap.yaml
- mcs-service.yaml
- mcs-deployment.yaml
- minio-operator.yaml

View File

@@ -0,0 +1,12 @@
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: mcs-sa-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: mcs-sa-role
subjects:
- kind: ServiceAccount
name: mcs-sa
namespace: default

View File

@@ -0,0 +1,77 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: mcs-sa-role
rules:
- apiGroups:
- ""
resources:
- namespaces
- secrets
- pods
- services
- events
- resourcequotas
verbs:
- get
- watch
- create
- list
- patch
- apiGroups:
- "storage.k8s.io"
resources:
- storageclasses
verbs:
- get
- watch
- create
- list
- patch
- apiGroups:
- apps
resources:
- statefulsets
- deployments
verbs:
- get
- create
- list
- patch
- watch
- update
- delete
- apiGroups:
- batch
resources:
- jobs
verbs:
- get
- create
- list
- patch
- watch
- update
- delete
- apiGroups:
- "certificates.k8s.io"
resources:
- "certificatesigningrequests"
- "certificatesigningrequests/approval"
- "certificatesigningrequests/status"
verbs:
- update
- create
- get
- apiGroups:
- operator.min.io
resources:
- "*"
verbs:
- "*"
- apiGroups:
- min.io
resources:
- "*"
verbs:
- "*"

View File

@@ -0,0 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: mcs-env
data:
MCS_PORT: "9090"
MCS_TLS_PORT: "9443"

View File

@@ -0,0 +1,27 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcs
spec:
replicas: 1
selector:
matchLabels:
app: mcs
template:
metadata:
labels:
app: mcs
spec:
serviceAccountName: m3-sa
containers:
- name: mcs
image: minio/mcs:latest
imagePullPolicy: "IfNotPresent"
args:
- /mcs
- server
ports:
- containerPort: 9090
name: http
- containerPort: 9433
name: https

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: mcs-sa
namespace: default

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: mcs
labels:
name: mcs
spec:
ports:
- port: 9090
name: http
- port: 9443
name: https
selector:
app: mcs

View File

@@ -0,0 +1,203 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: minioinstances.operator.min.io
spec:
group: operator.min.io
scope: Namespaced
names:
kind: MinIOInstance
singular: minioinstance
plural: minioinstances
versions:
- name: v1
served: true
storage: true
schema:
# openAPIV3Schema is the schema for validating custom objects.
# Refer https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#specifying-a-structural-schema
# for more details
openAPIV3Schema:
type: object
properties:
spec:
type: object
x-kubernetes-preserve-unknown-fields: true
properties:
replicas:
type: integer
minimum: 1
maximum: 32
image:
type: string
serviceName:
type: string
volumesPerServer:
type: integer
mountPath:
type: string
podManagementPolicy:
type: string
enum: [Parallel, OrderedReady]
default: Parallel
requestAutoCert:
type: boolean
default: false
version:
type: string
mountpath:
type: string
subpath:
type: string
mcs:
type: object
x-kubernetes-preserve-unknown-fields: true
properties:
image:
type: string
replicas:
type: integer
default: 2
mcsSecret:
type: object
properties:
name:
type: string
kes:
type: object
x-kubernetes-preserve-unknown-fields: true
properties:
image:
type: string
replicas:
type: integer
default: 2
kesSecret:
type: object
properties:
name:
type: string
status:
type: object
properties:
currentState:
type: string
subresources:
# status enables the status subresource.
status: {}
additionalPrinterColumns:
- name: Current State
type: string
jsonPath: ".status.currentState"
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: minio-operator-role
rules:
- apiGroups:
- ""
resources:
- namespaces
- secrets
- pods
- services
- events
verbs:
- get
- watch
- create
- list
- delete
- apiGroups:
- apps
resources:
- statefulsets
- deployments
verbs:
- get
- create
- list
- patch
- watch
- update
- delete
- apiGroups:
- batch
resources:
- jobs
verbs:
- get
- create
- list
- patch
- watch
- update
- delete
- apiGroups:
- "certificates.k8s.io"
resources:
- "certificatesigningrequests"
- "certificatesigningrequests/approval"
- "certificatesigningrequests/status"
verbs:
- update
- create
- get
- delete
- apiGroups:
- operator.min.io
resources:
- "*"
verbs:
- "*"
- apiGroups:
- min.io
resources:
- "*"
verbs:
- "*"
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: minio-operator
namespace: default
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: minio-operator-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: minio-operator-role
subjects:
- kind: ServiceAccount
name: minio-operator
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio-operator
namespace: default
spec:
replicas: 1
selector:
matchLabels:
name: minio-operator
template:
metadata:
labels:
name: minio-operator
spec:
serviceAccountName: minio-operator
containers:
- name: minio-operator
image: minio/k8s-operator:2.0.8
imagePullPolicy: IfNotPresent
# To specify cluster domain, un comment the following:
# env:
# - name: CLUSTER_DOMAIN
# value: mycluster.mydomain

44
k8s/create-kind.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/bin/bash
# setup environment variables based on flags to see if we should build the docker containers again
MCS_DOCKER="true"
# evaluate flags
# `-m` for mcs
while getopts ":m:" opt; do
case $opt in
m)
MCS_DOCKER="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
echo "Provisioning Kind"
kind create cluster --config kind-cluster.yaml
echo "Remove Master Taint"
kubectl taint nodes --all node-role.kubernetes.io/master-
echo "Install Contour"
kubectl apply -f https://projectcontour.io/quickstart/contour.yaml
kubectl patch daemonsets -n projectcontour envoy -p '{"spec":{"template":{"spec":{"nodeSelector":{"ingress-ready":"true"},"tolerations":[{"key":"node-role.kubernetes.io/master","operator":"Equal","effect":"NoSchedule"}]}}}}'
echo "install metrics server"
kubectl apply -f metrics-dev.yaml
# Whether or not to build the m3 container and load it to kind or just load it
if [[ $MCS_DOCKER == "true" ]]; then
# Build mkube
make --directory=".." k8sdev TAG=minio/mcs:latest
else
kind load docker-image minio/mcs:latest
fi
echo "done"

3
k8s/getoperator.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
# Get's the latest deployment file from MinIO Operator
curl https://raw.githubusercontent.com/minio/minio-operator/master/minio-operator.yaml > base/minio-operator.yaml

22
k8s/kind-cluster.yaml Normal file
View File

@@ -0,0 +1,22 @@
# three node (two workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 8844
protocol: TCP
- containerPort: 443
hostPort: 8843
protocol: TCP
#- role: worker
#- role: worker
#- role: worker
#- role: worker

153
k8s/metrics-dev.yaml Normal file
View File

@@ -0,0 +1,153 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:aggregated-metrics-reader
labels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- pods
- nodes
- nodes/stats
- namespaces
- configmaps
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
name: v1beta1.metrics.k8s.io
spec:
service:
name: metrics-server
namespace: kube-system
group: metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
name: metrics-server
namespace: kube-system
labels:
kubernetes.io/name: "Metrics-server"
kubernetes.io/cluster-service: "true"
spec:
selector:
k8s-app: metrics-server
ports:
- port: 443
protocol: TCP
targetPort: main-port
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: metrics-server
namespace: kube-system
labels:
k8s-app: metrics-server
spec:
selector:
matchLabels:
k8s-app: metrics-server
template:
metadata:
name: metrics-server
labels:
k8s-app: metrics-server
spec:
serviceAccountName: metrics-server
volumes:
# mount in tmp so we can safely use from-scratch images and/or read-only containers
- name: tmp-dir
emptyDir: {}
containers:
- name: metrics-server
image: k8s.gcr.io/metrics-server-amd64:v0.3.6
args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP
ports:
- name: main-port
containerPort: 4443
protocol: TCP
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
imagePullPolicy: Always
volumeMounts:
- name: tmp-dir
mountPath: /tmp
nodeSelector:
beta.kubernetes.io/os: linux
kubernetes.io/arch: "amd64"

View File

@@ -0,0 +1,11 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# beginning of customizations
resources:
- mcs-service-account.yaml
- mcs-cluster-role.yaml
- mcs-cluster-role-binding.yaml
- mcs-configmap.yaml
- mcs-service.yaml
- mcs-deployment.yaml
- minio-operator.yaml

View File

@@ -0,0 +1,12 @@
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: mcs-sa-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: mcs-sa-role
subjects:
- kind: ServiceAccount
name: mcs-sa
namespace: default

View File

@@ -0,0 +1,77 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: mcs-sa-role
rules:
- apiGroups:
- ""
resources:
- namespaces
- secrets
- pods
- services
- events
- resourcequotas
verbs:
- get
- watch
- create
- list
- patch
- apiGroups:
- "storage.k8s.io"
resources:
- storageclasses
verbs:
- get
- watch
- create
- list
- patch
- apiGroups:
- apps
resources:
- statefulsets
- deployments
verbs:
- get
- create
- list
- patch
- watch
- update
- delete
- apiGroups:
- batch
resources:
- jobs
verbs:
- get
- create
- list
- patch
- watch
- update
- delete
- apiGroups:
- "certificates.k8s.io"
resources:
- "certificatesigningrequests"
- "certificatesigningrequests/approval"
- "certificatesigningrequests/status"
verbs:
- update
- create
- get
- apiGroups:
- operator.min.io
resources:
- "*"
verbs:
- "*"
- apiGroups:
- min.io
resources:
- "*"
verbs:
- "*"

View File

@@ -0,0 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: mcs-env
data:
MCS_PORT: "9090"
MCS_TLS_PORT: "9443"

View File

@@ -0,0 +1,30 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcs
spec:
replicas: 1
selector:
matchLabels:
app: mcs
template:
metadata:
labels:
app: mcs
spec:
serviceAccountName: m3-sa
containers:
- name: mcs
image: minio/mcs:latest
imagePullPolicy: "IfNotPresent"
env:
- name: MCS_OPERATOR_MODE
value: "on"
args:
- /mcs
- server
ports:
- containerPort: 9090
name: http
- containerPort: 9433
name: https

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: mcs-sa
namespace: default

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: mcs
labels:
name: mcs
spec:
ports:
- port: 9090
name: http
- port: 9443
name: https
selector:
app: mcs

View File

@@ -0,0 +1,203 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: minioinstances.operator.min.io
spec:
group: operator.min.io
scope: Namespaced
names:
kind: MinIOInstance
singular: minioinstance
plural: minioinstances
versions:
- name: v1
served: true
storage: true
schema:
# openAPIV3Schema is the schema for validating custom objects.
# Refer https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#specifying-a-structural-schema
# for more details
openAPIV3Schema:
type: object
properties:
spec:
type: object
x-kubernetes-preserve-unknown-fields: true
properties:
replicas:
type: integer
minimum: 1
maximum: 32
image:
type: string
serviceName:
type: string
volumesPerServer:
type: integer
mountPath:
type: string
podManagementPolicy:
type: string
enum: [Parallel, OrderedReady]
default: Parallel
requestAutoCert:
type: boolean
default: false
version:
type: string
mountpath:
type: string
subpath:
type: string
mcs:
type: object
x-kubernetes-preserve-unknown-fields: true
properties:
image:
type: string
replicas:
type: integer
default: 2
mcsSecret:
type: object
properties:
name:
type: string
kes:
type: object
x-kubernetes-preserve-unknown-fields: true
properties:
image:
type: string
replicas:
type: integer
default: 2
kesSecret:
type: object
properties:
name:
type: string
status:
type: object
properties:
currentState:
type: string
subresources:
# status enables the status subresource.
status: {}
additionalPrinterColumns:
- name: Current State
type: string
jsonPath: ".status.currentState"
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: minio-operator-role
rules:
- apiGroups:
- ""
resources:
- namespaces
- secrets
- pods
- services
- events
verbs:
- get
- watch
- create
- list
- delete
- apiGroups:
- apps
resources:
- statefulsets
- deployments
verbs:
- get
- create
- list
- patch
- watch
- update
- delete
- apiGroups:
- batch
resources:
- jobs
verbs:
- get
- create
- list
- patch
- watch
- update
- delete
- apiGroups:
- "certificates.k8s.io"
resources:
- "certificatesigningrequests"
- "certificatesigningrequests/approval"
- "certificatesigningrequests/status"
verbs:
- update
- create
- get
- delete
- apiGroups:
- operator.min.io
resources:
- "*"
verbs:
- "*"
- apiGroups:
- min.io
resources:
- "*"
verbs:
- "*"
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: minio-operator
namespace: default
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: minio-operator-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: minio-operator-role
subjects:
- kind: ServiceAccount
name: minio-operator
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio-operator
namespace: default
spec:
replicas: 1
selector:
matchLabels:
name: minio-operator
template:
metadata:
labels:
name: minio-operator
spec:
serviceAccountName: minio-operator
containers:
- name: minio-operator
image: minio/k8s-operator:2.0.8
imagePullPolicy: IfNotPresent
# To specify cluster domain, un comment the following:
# env:
# - name: CLUSTER_DOMAIN
# value: mycluster.mydomain

20
k8s/tools.go Normal file
View File

@@ -0,0 +1,20 @@
// This file is part of MinIO Kubernetes Cloud
// Copyright (c) 2019 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 <http://www.gnu.org/licenses/>.
// This package imports things required by build scripts, to force `go mod` to see them as dependencies
package k8s
//import _ "k8s.io/code-generator"

35
k8s/update-codegen.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
# generate the code with:
# --output-base because this script should also be able to run inside the vendor dir of
# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
# instead of the $GOPATH directly. For normal projects this can be dropped.
bash "${CODEGEN_PKG}"/generate-groups.sh "all" \
github.com/minio/mcs/pkg/generated \
github.com/minio/mcs/pkg/apis \
mkube:v1 \
--go-header-file "${SCRIPT_ROOT}"/k8s/boilerplate.go.txt
# To use your own boilerplate text append:
# --go-header-file "${SCRIPT_ROOT}"/hack/custom-boilerplate.go.txt

View File

@@ -34,12 +34,13 @@ import (
// swagger:model addPolicyRequest
type AddPolicyRequest struct {
// definition
Definition string `json:"definition,omitempty"`
// name
// Required: true
Name *string `json:"name"`
// policy
// Required: true
Policy *string `json:"policy"`
}
// Validate validates this add policy request
@@ -50,6 +51,10 @@ func (m *AddPolicyRequest) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validatePolicy(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
@@ -65,6 +70,15 @@ func (m *AddPolicyRequest) validateName(formats strfmt.Registry) error {
return nil
}
func (m *AddPolicyRequest) validatePolicy(formats strfmt.Registry) error {
if err := validate.Required("policy", "body", m.Policy); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *AddPolicyRequest) MarshalBinary() ([]byte, error) {
if m == nil {

View File

@@ -38,6 +38,10 @@ type AddUserRequest struct {
// Required: true
AccessKey *string `json:"accessKey"`
// groups
// Required: true
Groups []string `json:"groups"`
// secret key
// Required: true
SecretKey *string `json:"secretKey"`
@@ -51,6 +55,10 @@ func (m *AddUserRequest) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateGroups(formats); err != nil {
res = append(res, err)
}
if err := m.validateSecretKey(formats); err != nil {
res = append(res, err)
}
@@ -70,6 +78,15 @@ func (m *AddUserRequest) validateAccessKey(formats strfmt.Registry) error {
return nil
}
func (m *AddUserRequest) validateGroups(formats strfmt.Registry) error {
if err := validate.Required("groups", "body", m.Groups); err != nil {
return err
}
return nil
}
func (m *AddUserRequest) validateSecretKey(formats strfmt.Registry) error {
if err := validate.Required("secretKey", "body", m.SecretKey); err != nil {

View File

@@ -61,7 +61,7 @@ func init() {
}
func (m BucketAccess) validateBucketAccessEnum(path, location string, value BucketAccess) error {
if err := validate.Enum(path, location, value, bucketAccessEnum); err != nil {
if err := validate.EnumCase(path, location, value, bucketAccessEnum, true); err != nil {
return err
}
return nil

View File

@@ -0,0 +1,98 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// BulkUserGroups bulk user groups
//
// swagger:model bulkUserGroups
type BulkUserGroups struct {
// groups
// Required: true
Groups []string `json:"groups"`
// users
// Required: true
Users []string `json:"users"`
}
// Validate validates this bulk user groups
func (m *BulkUserGroups) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateGroups(formats); err != nil {
res = append(res, err)
}
if err := m.validateUsers(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *BulkUserGroups) validateGroups(formats strfmt.Registry) error {
if err := validate.Required("groups", "body", m.Groups); err != nil {
return err
}
return nil
}
func (m *BulkUserGroups) validateUsers(formats strfmt.Registry) error {
if err := validate.Required("users", "body", m.Users); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *BulkUserGroups) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *BulkUserGroups) UnmarshalBinary(b []byte) error {
var res BulkUserGroups
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,244 @@
// 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 <http://www.gnu.org/licenses/>.
//
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 (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// CreateTenantRequest create tenant request
//
// swagger:model createTenantRequest
type CreateTenantRequest struct {
// access key
AccessKey string `json:"access_key,omitempty"`
// annotations
Annotations map[string]string `json:"annotations,omitempty"`
// enable mcs
EnableMcs *bool `json:"enable_mcs,omitempty"`
// enable ssl
EnableSsl *bool `json:"enable_ssl,omitempty"`
// image
Image string `json:"image,omitempty"`
// mounth path
MounthPath string `json:"mounth_path,omitempty"`
// name
// Required: true
// Pattern: ^[a-z0-9-]{3,63}$
Name *string `json:"name"`
// namespace
// Required: true
Namespace *string `json:"namespace"`
// secret key
SecretKey string `json:"secret_key,omitempty"`
// service name
ServiceName string `json:"service_name,omitempty"`
// volume configuration
// Required: true
VolumeConfiguration *CreateTenantRequestVolumeConfiguration `json:"volume_configuration"`
// volumes per server
VolumesPerServer int64 `json:"volumes_per_server,omitempty"`
// zones
Zones []*Zone `json:"zones"`
}
// Validate validates this create tenant request
func (m *CreateTenantRequest) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateName(formats); err != nil {
res = append(res, err)
}
if err := m.validateNamespace(formats); err != nil {
res = append(res, err)
}
if err := m.validateVolumeConfiguration(formats); err != nil {
res = append(res, err)
}
if err := m.validateZones(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *CreateTenantRequest) validateName(formats strfmt.Registry) error {
if err := validate.Required("name", "body", m.Name); err != nil {
return err
}
if err := validate.Pattern("name", "body", string(*m.Name), `^[a-z0-9-]{3,63}$`); err != nil {
return err
}
return nil
}
func (m *CreateTenantRequest) validateNamespace(formats strfmt.Registry) error {
if err := validate.Required("namespace", "body", m.Namespace); err != nil {
return err
}
return nil
}
func (m *CreateTenantRequest) validateVolumeConfiguration(formats strfmt.Registry) error {
if err := validate.Required("volume_configuration", "body", m.VolumeConfiguration); err != nil {
return err
}
if m.VolumeConfiguration != nil {
if err := m.VolumeConfiguration.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("volume_configuration")
}
return err
}
}
return nil
}
func (m *CreateTenantRequest) validateZones(formats strfmt.Registry) error {
if swag.IsZero(m.Zones) { // not required
return nil
}
for i := 0; i < len(m.Zones); i++ {
if swag.IsZero(m.Zones[i]) { // not required
continue
}
if m.Zones[i] != nil {
if err := m.Zones[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("zones" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *CreateTenantRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *CreateTenantRequest) UnmarshalBinary(b []byte) error {
var res CreateTenantRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}
// CreateTenantRequestVolumeConfiguration create tenant request volume configuration
//
// swagger:model CreateTenantRequestVolumeConfiguration
type CreateTenantRequestVolumeConfiguration struct {
// size
// Required: true
Size *string `json:"size"`
// storage class
StorageClass string `json:"storage_class,omitempty"`
}
// Validate validates this create tenant request volume configuration
func (m *CreateTenantRequestVolumeConfiguration) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateSize(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *CreateTenantRequestVolumeConfiguration) validateSize(formats strfmt.Registry) error {
if err := validate.Required("volume_configuration"+"."+"size", "body", m.Size); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *CreateTenantRequestVolumeConfiguration) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *CreateTenantRequestVolumeConfiguration) UnmarshalBinary(b []byte) error {
var res CreateTenantRequestVolumeConfiguration
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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"
)
// CreateTenantResponse create tenant response
//
// swagger:model createTenantResponse
type CreateTenantResponse struct {
// access key
AccessKey string `json:"access_key,omitempty"`
// secret key
SecretKey string `json:"secret_key,omitempty"`
}
// Validate validates this create tenant response
func (m *CreateTenantResponse) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *CreateTenantResponse) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *CreateTenantResponse) UnmarshalBinary(b []byte) error {
var res CreateTenantResponse
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,100 @@
// 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 <http://www.gnu.org/licenses/>.
//
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 (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// ListTenantsResponse list tenants response
//
// swagger:model listTenantsResponse
type ListTenantsResponse struct {
// list of resulting tenants
Tenants []*TenantList `json:"tenants"`
// number of tenants accessible to tenant user
Total int64 `json:"total,omitempty"`
}
// Validate validates this list tenants response
func (m *ListTenantsResponse) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateTenants(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ListTenantsResponse) validateTenants(formats strfmt.Registry) error {
if swag.IsZero(m.Tenants) { // not required
return nil
}
for i := 0; i < len(m.Tenants); i++ {
if swag.IsZero(m.Tenants[i]) { // not required
continue
}
if m.Tenants[i] != nil {
if err := m.Tenants[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("tenants" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *ListTenantsResponse) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ListTenantsResponse) UnmarshalBinary(b []byte) error {
var res ListTenantsResponse
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -37,7 +37,7 @@ import (
type LoginDetails struct {
// login strategy
// Enum: [form redirect]
// Enum: [form redirect service-account]
LoginStrategy string `json:"loginStrategy,omitempty"`
// redirect
@@ -62,7 +62,7 @@ var loginDetailsTypeLoginStrategyPropEnum []interface{}
func init() {
var res []string
if err := json.Unmarshal([]byte(`["form","redirect"]`), &res); err != nil {
if err := json.Unmarshal([]byte(`["form","redirect","service-account"]`), &res); err != nil {
panic(err)
}
for _, v := range res {
@@ -77,11 +77,14 @@ const (
// LoginDetailsLoginStrategyRedirect captures enum value "redirect"
LoginDetailsLoginStrategyRedirect string = "redirect"
// LoginDetailsLoginStrategyServiceAccount captures enum value "service-account"
LoginDetailsLoginStrategyServiceAccount string = "service-account"
)
// prop value enum
func (m *LoginDetails) validateLoginStrategyEnum(path, location string, value string) error {
if err := validate.Enum(path, location, value, loginDetailsTypeLoginStrategyPropEnum); err != nil {
if err := validate.EnumCase(path, location, value, loginDetailsTypeLoginStrategyPropEnum, true); err != nil {
return err
}
return nil

View File

@@ -0,0 +1,98 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// LoginOauth2AuthRequest login oauth2 auth request
//
// swagger:model loginOauth2AuthRequest
type LoginOauth2AuthRequest struct {
// code
// Required: true
Code *string `json:"code"`
// state
// Required: true
State *string `json:"state"`
}
// Validate validates this login oauth2 auth request
func (m *LoginOauth2AuthRequest) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateCode(formats); err != nil {
res = append(res, err)
}
if err := m.validateState(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *LoginOauth2AuthRequest) validateCode(formats strfmt.Registry) error {
if err := validate.Required("code", "body", m.Code); err != nil {
return err
}
return nil
}
func (m *LoginOauth2AuthRequest) validateState(formats strfmt.Registry) error {
if err := validate.Required("state", "body", m.State); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *LoginOauth2AuthRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *LoginOauth2AuthRequest) UnmarshalBinary(b []byte) error {
var res LoginOauth2AuthRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,81 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// LoginOperatorRequest login operator request
//
// swagger:model loginOperatorRequest
type LoginOperatorRequest struct {
// jwt
// Required: true
Jwt *string `json:"jwt"`
}
// Validate validates this login operator request
func (m *LoginOperatorRequest) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateJwt(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *LoginOperatorRequest) validateJwt(formats strfmt.Registry) error {
if err := validate.Required("jwt", "body", m.Jwt); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *LoginOperatorRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *LoginOperatorRequest) UnmarshalBinary(b []byte) error {
var res LoginOperatorRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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 (
"encoding/json"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/validate"
)
// NofiticationService nofitication service
//
// swagger:model nofiticationService
type NofiticationService string
const (
// NofiticationServiceWebhook captures enum value "webhook"
NofiticationServiceWebhook NofiticationService = "webhook"
// NofiticationServiceAmqp captures enum value "amqp"
NofiticationServiceAmqp NofiticationService = "amqp"
// NofiticationServiceKafka captures enum value "kafka"
NofiticationServiceKafka NofiticationService = "kafka"
// NofiticationServiceMqtt captures enum value "mqtt"
NofiticationServiceMqtt NofiticationService = "mqtt"
// NofiticationServiceNats captures enum value "nats"
NofiticationServiceNats NofiticationService = "nats"
// NofiticationServiceNsq captures enum value "nsq"
NofiticationServiceNsq NofiticationService = "nsq"
// NofiticationServiceMysql captures enum value "mysql"
NofiticationServiceMysql NofiticationService = "mysql"
// NofiticationServicePostgres captures enum value "postgres"
NofiticationServicePostgres NofiticationService = "postgres"
// NofiticationServiceElasticsearch captures enum value "elasticsearch"
NofiticationServiceElasticsearch NofiticationService = "elasticsearch"
// NofiticationServiceRedis captures enum value "redis"
NofiticationServiceRedis NofiticationService = "redis"
)
// for schema
var nofiticationServiceEnum []interface{}
func init() {
var res []NofiticationService
if err := json.Unmarshal([]byte(`["webhook","amqp","kafka","mqtt","nats","nsq","mysql","postgres","elasticsearch","redis"]`), &res); err != nil {
panic(err)
}
for _, v := range res {
nofiticationServiceEnum = append(nofiticationServiceEnum, v)
}
}
func (m NofiticationService) validateNofiticationServiceEnum(path, location string, value NofiticationService) error {
if err := validate.EnumCase(path, location, value, nofiticationServiceEnum, true); err != nil {
return err
}
return nil
}
// Validate validates this nofitication service
func (m NofiticationService) Validate(formats strfmt.Registry) error {
var res []error
// value enum
if err := m.validateNofiticationServiceEnum("", "body", m); err != nil {
return err
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,97 @@
// 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 <http://www.gnu.org/licenses/>.
//
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 (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NotifEndpointResponse notif endpoint response
//
// swagger:model notifEndpointResponse
type NotifEndpointResponse struct {
// notification endpoints
NotificationEndpoints []*NotificationEndpointItem `json:"notification_endpoints"`
}
// Validate validates this notif endpoint response
func (m *NotifEndpointResponse) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateNotificationEndpoints(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *NotifEndpointResponse) validateNotificationEndpoints(formats strfmt.Registry) error {
if swag.IsZero(m.NotificationEndpoints) { // not required
return nil
}
for i := 0; i < len(m.NotificationEndpoints); i++ {
if swag.IsZero(m.NotificationEndpoints[i]) { // not required
continue
}
if m.NotificationEndpoints[i] != nil {
if err := m.NotificationEndpoints[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("notification_endpoints" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *NotifEndpointResponse) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *NotifEndpointResponse) UnmarshalBinary(b []byte) error {
var res NotifEndpointResponse
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,129 @@
// 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 <http://www.gnu.org/licenses/>.
//
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 (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// NotificationDeleteRequest notification delete request
//
// swagger:model notificationDeleteRequest
type NotificationDeleteRequest struct {
// filter specific type of event. Defaults to all event (default: '[put,delete,get]')
// Required: true
// Min Length: 1
Events []NotificationEventType `json:"events"`
// filter event associated to the specified prefix
// Required: true
Prefix *string `json:"prefix"`
// filter event associated to the specified suffix
// Required: true
Suffix *string `json:"suffix"`
}
// Validate validates this notification delete request
func (m *NotificationDeleteRequest) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateEvents(formats); err != nil {
res = append(res, err)
}
if err := m.validatePrefix(formats); err != nil {
res = append(res, err)
}
if err := m.validateSuffix(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *NotificationDeleteRequest) validateEvents(formats strfmt.Registry) error {
if err := validate.Required("events", "body", m.Events); err != nil {
return err
}
for i := 0; i < len(m.Events); i++ {
if err := m.Events[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("events" + "." + strconv.Itoa(i))
}
return err
}
}
return nil
}
func (m *NotificationDeleteRequest) validatePrefix(formats strfmt.Registry) error {
if err := validate.Required("prefix", "body", m.Prefix); err != nil {
return err
}
return nil
}
func (m *NotificationDeleteRequest) validateSuffix(formats strfmt.Registry) error {
if err := validate.Required("suffix", "body", m.Suffix); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *NotificationDeleteRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *NotificationDeleteRequest) UnmarshalBinary(b []byte) error {
var res NotificationDeleteRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,114 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// NotificationEndpoint notification endpoint
//
// swagger:model notificationEndpoint
type NotificationEndpoint struct {
// account id
// Required: true
AccountID *string `json:"account_id"`
// properties
// Required: true
Properties map[string]string `json:"properties"`
// service
// Required: true
Service NofiticationService `json:"service"`
}
// Validate validates this notification endpoint
func (m *NotificationEndpoint) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateAccountID(formats); err != nil {
res = append(res, err)
}
if err := m.validateProperties(formats); err != nil {
res = append(res, err)
}
if err := m.validateService(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *NotificationEndpoint) validateAccountID(formats strfmt.Registry) error {
if err := validate.Required("account_id", "body", m.AccountID); err != nil {
return err
}
return nil
}
func (m *NotificationEndpoint) validateProperties(formats strfmt.Registry) error {
return nil
}
func (m *NotificationEndpoint) validateService(formats strfmt.Registry) error {
if err := m.Service.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("service")
}
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *NotificationEndpoint) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *NotificationEndpoint) UnmarshalBinary(b []byte) error {
var res NotificationEndpoint
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,92 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// NotificationEndpointItem notification endpoint item
//
// swagger:model notificationEndpointItem
type NotificationEndpointItem struct {
// account id
AccountID string `json:"account_id,omitempty"`
// service
Service NofiticationService `json:"service,omitempty"`
// status
Status string `json:"status,omitempty"`
}
// Validate validates this notification endpoint item
func (m *NotificationEndpointItem) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateService(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *NotificationEndpointItem) validateService(formats strfmt.Registry) error {
if swag.IsZero(m.Service) { // not required
return nil
}
if err := m.Service.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("service")
}
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *NotificationEndpointItem) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *NotificationEndpointItem) UnmarshalBinary(b []byte) error {
var res NotificationEndpointItem
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -61,7 +61,7 @@ func init() {
}
func (m NotificationEventType) validateNotificationEventTypeEnum(path, location string, value NotificationEventType) error {
if err := validate.Enum(path, location, value, notificationEventTypeEnum); err != nil {
if err := validate.EnumCase(path, location, value, notificationEventTypeEnum, true); err != nil {
return err
}
return nil

View File

@@ -23,9 +23,6 @@ package models
// Editing this file might prove futile when you re-run the swagger generate command
import (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
@@ -38,49 +35,12 @@ type Policy struct {
// name
Name string `json:"name,omitempty"`
// statements
Statements []*Statement `json:"statements"`
// version
Version string `json:"version,omitempty"`
// policy
Policy string `json:"policy,omitempty"`
}
// Validate validates this policy
func (m *Policy) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateStatements(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *Policy) validateStatements(formats strfmt.Registry) error {
if swag.IsZero(m.Statements) { // not required
return nil
}
for i := 0; i < len(m.Statements); i++ {
if swag.IsZero(m.Statements[i]) { // not required
continue
}
if m.Statements[i] != nil {
if err := m.Statements[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("statements" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}

View File

@@ -58,7 +58,7 @@ func init() {
}
func (m PolicyEntity) validatePolicyEntityEnum(path, location string, value PolicyEntity) error {
if err := validate.Enum(path, location, value, policyEntityEnum); err != nil {
if err := validate.EnumCase(path, location, value, policyEntityEnum, true); err != nil {
return err
}
return nil

View File

@@ -24,14 +24,46 @@ package models
import (
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// Principal principal
//
// swagger:model principal
type Principal string
type Principal struct {
// access key ID
AccessKeyID string `json:"accessKeyID,omitempty"`
// actions
Actions []string `json:"actions"`
// secret access key
SecretAccessKey string `json:"secretAccessKey,omitempty"`
// session token
SessionToken string `json:"sessionToken,omitempty"`
}
// Validate validates this principal
func (m Principal) Validate(formats strfmt.Registry) error {
func (m *Principal) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *Principal) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *Principal) UnmarshalBinary(b []byte) error {
var res Principal
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -73,7 +73,7 @@ func init() {
}
func (m ProfilerType) validateProfilerTypeEnum(path, location string, value ProfilerType) error {
if err := validate.Enum(path, location, value, profilerTypeEnum); err != nil {
if err := validate.EnumCase(path, location, value, profilerTypeEnum, true); err != nil {
return err
}
return nil

100
models/resource_quota.go Normal file
View File

@@ -0,0 +1,100 @@
// 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 <http://www.gnu.org/licenses/>.
//
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 (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// ResourceQuota resource quota
//
// swagger:model resourceQuota
type ResourceQuota struct {
// elements
Elements []*ResourceQuotaElement `json:"elements"`
// name
Name string `json:"name,omitempty"`
}
// Validate validates this resource quota
func (m *ResourceQuota) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateElements(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ResourceQuota) validateElements(formats strfmt.Registry) error {
if swag.IsZero(m.Elements) { // not required
return nil
}
for i := 0; i < len(m.Elements); i++ {
if swag.IsZero(m.Elements[i]) { // not required
continue
}
if m.Elements[i] != nil {
if err := m.Elements[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("elements" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *ResourceQuota) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ResourceQuota) UnmarshalBinary(b []byte) error {
var res ResourceQuota
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,66 @@
// 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 <http://www.gnu.org/licenses/>.
//
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"
)
// ResourceQuotaElement resource quota element
//
// swagger:model resourceQuotaElement
type ResourceQuotaElement struct {
// hard
Hard int64 `json:"hard,omitempty"`
// name
Name string `json:"name,omitempty"`
// used
Used int64 `json:"used,omitempty"`
}
// Validate validates this resource quota element
func (m *ResourceQuotaElement) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *ResourceQuotaElement) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ResourceQuotaElement) UnmarshalBinary(b []byte) error {
var res ResourceQuotaElement
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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
}

View File

@@ -27,28 +27,22 @@ import (
"github.com/go-openapi/swag"
)
// Statement statement
// ServiceAccountRequest service account request
//
// swagger:model statement
type Statement struct {
// swagger:model serviceAccountRequest
type ServiceAccountRequest struct {
// actions
Actions []string `json:"actions"`
// effect
Effect string `json:"effect,omitempty"`
// resources
Resources []string `json:"resources"`
// policy to be applied to the Service Account if any
Policy string `json:"policy,omitempty"`
}
// Validate validates this statement
func (m *Statement) Validate(formats strfmt.Registry) error {
// Validate validates this service account request
func (m *ServiceAccountRequest) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *Statement) MarshalBinary() ([]byte, error) {
func (m *ServiceAccountRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
@@ -56,8 +50,8 @@ func (m *Statement) MarshalBinary() ([]byte, error) {
}
// UnmarshalBinary interface implementation
func (m *Statement) UnmarshalBinary(b []byte) error {
var res Statement
func (m *ServiceAccountRequest) UnmarshalBinary(b []byte) error {
var res ServiceAccountRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}

View File

@@ -0,0 +1,37 @@
// 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 <http://www.gnu.org/licenses/>.
//
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"
)
// ServiceAccounts service accounts
//
// swagger:model serviceAccounts
type ServiceAccounts []string
// Validate validates this service accounts
func (m ServiceAccounts) Validate(formats strfmt.Registry) error {
return nil
}

View File

@@ -36,6 +36,9 @@ import (
// swagger:model sessionResponse
type SessionResponse struct {
// pages
Pages []string `json:"pages"`
// status
// Enum: [ok]
Status string `json:"status,omitempty"`
@@ -75,7 +78,7 @@ const (
// prop value enum
func (m *SessionResponse) validateStatusEnum(path, location string, value string) error {
if err := validate.Enum(path, location, value, sessionResponseTypeStatusPropEnum); err != nil {
if err := validate.EnumCase(path, location, value, sessionResponseTypeStatusPropEnum, true); err != nil {
return err
}
return nil

133
models/tenant.go Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
//
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 (
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// Tenant tenant
//
// swagger:model tenant
type Tenant struct {
// creation date
CreationDate string `json:"creation_date,omitempty"`
// current state
CurrentState string `json:"currentState,omitempty"`
// image
Image string `json:"image,omitempty"`
// instance count
InstanceCount int64 `json:"instance_count,omitempty"`
// name
Name string `json:"name,omitempty"`
// namespace
Namespace string `json:"namespace,omitempty"`
// total size
TotalSize int64 `json:"total_size,omitempty"`
// used size
UsedSize int64 `json:"used_size,omitempty"`
// volume count
VolumeCount int64 `json:"volume_count,omitempty"`
// volume size
VolumeSize int64 `json:"volume_size,omitempty"`
// volumes per server
VolumesPerServer int64 `json:"volumes_per_server,omitempty"`
// zone count
ZoneCount int64 `json:"zone_count,omitempty"`
// zones
Zones []*Zone `json:"zones"`
}
// Validate validates this tenant
func (m *Tenant) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateZones(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *Tenant) validateZones(formats strfmt.Registry) error {
if swag.IsZero(m.Zones) { // not required
return nil
}
for i := 0; i < len(m.Zones); i++ {
if swag.IsZero(m.Zones[i]) { // not required
continue
}
if m.Zones[i] != nil {
if err := m.Zones[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("zones" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
// MarshalBinary interface implementation
func (m *Tenant) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *Tenant) UnmarshalBinary(b []byte) error {
var res Tenant
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

81
models/tenant_list.go Normal file
View File

@@ -0,0 +1,81 @@
// 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 <http://www.gnu.org/licenses/>.
//
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"
)
// TenantList tenant list
//
// swagger:model tenantList
type TenantList struct {
// creation date
CreationDate string `json:"creation_date,omitempty"`
// current state
CurrentState string `json:"currentState,omitempty"`
// instance count
InstanceCount int64 `json:"instance_count,omitempty"`
// name
Name string `json:"name,omitempty"`
// namespace
Namespace string `json:"namespace,omitempty"`
// volume count
VolumeCount int64 `json:"volume_count,omitempty"`
// volume size
VolumeSize int64 `json:"volume_size,omitempty"`
// zone count
ZoneCount int64 `json:"zone_count,omitempty"`
}
// Validate validates this tenant list
func (m *TenantList) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *TenantList) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *TenantList) UnmarshalBinary(b []byte) error {
var res TenantList
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,85 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// UpdateTenantRequest update tenant request
//
// swagger:model updateTenantRequest
type UpdateTenantRequest struct {
// image
// Pattern: ^((.*?)/(.*?):(.+))$
Image string `json:"image,omitempty"`
}
// Validate validates this update tenant request
func (m *UpdateTenantRequest) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateImage(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *UpdateTenantRequest) validateImage(formats strfmt.Registry) error {
if swag.IsZero(m.Image) { // not required
return nil
}
if err := validate.Pattern("image", "body", string(m.Image), `^((.*?)/(.*?):(.+))$`); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *UpdateTenantRequest) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *UpdateTenantRequest) UnmarshalBinary(b []byte) error {
var res UpdateTenantRequest
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

98
models/update_user.go Normal file
View File

@@ -0,0 +1,98 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// UpdateUser update user
//
// swagger:model updateUser
type UpdateUser struct {
// groups
// Required: true
Groups []string `json:"groups"`
// status
// Required: true
Status *string `json:"status"`
}
// Validate validates this update user
func (m *UpdateUser) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateGroups(formats); err != nil {
res = append(res, err)
}
if err := m.validateStatus(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *UpdateUser) validateGroups(formats strfmt.Registry) error {
if err := validate.Required("groups", "body", m.Groups); err != nil {
return err
}
return nil
}
func (m *UpdateUser) validateStatus(formats strfmt.Registry) error {
if err := validate.Required("status", "body", m.Status); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *UpdateUser) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *UpdateUser) UnmarshalBinary(b []byte) error {
var res UpdateUser
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,81 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// UpdateUserGroups update user groups
//
// swagger:model updateUserGroups
type UpdateUserGroups struct {
// groups
// Required: true
Groups []string `json:"groups"`
}
// Validate validates this update user groups
func (m *UpdateUserGroups) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateGroups(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *UpdateUserGroups) validateGroups(formats strfmt.Registry) error {
if err := validate.Required("groups", "body", m.Groups); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *UpdateUserGroups) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *UpdateUserGroups) UnmarshalBinary(b []byte) error {
var res UpdateUserGroups
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

98
models/zone.go Normal file
View File

@@ -0,0 +1,98 @@
// 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 <http://www.gnu.org/licenses/>.
//
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/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// Zone zone
//
// swagger:model zone
type Zone struct {
// name
// Required: true
Name *string `json:"name"`
// servers
// Required: true
Servers *int64 `json:"servers"`
}
// Validate validates this zone
func (m *Zone) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateName(formats); err != nil {
res = append(res, err)
}
if err := m.validateServers(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *Zone) validateName(formats strfmt.Registry) error {
if err := validate.Required("name", "body", m.Name); err != nil {
return err
}
return nil
}
func (m *Zone) validateServers(formats strfmt.Registry) error {
if err := validate.Required("servers", "body", m.Servers); err != nil {
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *Zone) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *Zone) UnmarshalBinary(b []byte) error {
var res Zone
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -14,24 +14,15 @@
// 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 main
package acl
import (
"fmt"
"strings"
"github.com/minio/cli"
"github.com/minio/m3/mcs/pkg"
"github.com/minio/minio/pkg/env"
)
// starts the server
var versionCmd = cli.Command{
Name: "version",
Usage: "shows mcs version",
Action: version,
}
// starts the controller
func version(ctx *cli.Context) error {
fmt.Printf("MCS version %s (%s - %s. Commit %s)", pkg.Version, pkg.ReleaseTag, pkg.ReleaseTime, pkg.CommitID)
return nil
// GetOperatorMode gets MCS Operator mode status set on env variable or default one
func GetOperatorMode() bool {
return strings.ToLower(env.Get(mcsOperatorMode, "off")) == "on"
}

21
pkg/acl/const.go Normal file
View File

@@ -0,0 +1,21 @@
// 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 <http://www.gnu.org/licenses/>.
package acl
const (
mcsOperatorMode = "MCS_OPERATOR_MODE"
)

315
pkg/acl/endpoints.go Normal file
View File

@@ -0,0 +1,315 @@
// 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 <http://www.gnu.org/licenses/>.
package acl
import (
iampolicy "github.com/minio/minio/pkg/iam/policy"
)
// endpoints definition
var (
configuration = "/configurations-list"
users = "/users"
groups = "/groups"
iamPolicies = "/policies"
dashboard = "/dashboard"
profiling = "/profiling"
trace = "/trace"
logs = "/logs"
watch = "/watch"
notifications = "/notification-endpoints"
buckets = "/buckets"
bucketsDetail = "/buckets/:bucketName"
serviceAccounts = "/service-accounts"
tenants = "/tenants"
tenantsDetail = "/tenants/:tenantName"
heal = "/heal"
)
type ConfigurationActionSet struct {
actionTypes iampolicy.ActionSet
actions iampolicy.ActionSet
}
// configurationActionSet contains the list of admin actions required for this endpoint to work
var configurationActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.ConfigUpdateAdminAction,
),
}
// logsActionSet contains the list of admin actions required for this endpoint to work
var logsActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.ConsoleLogAdminAction,
),
}
// dashboardActionSet contains the list of admin actions required for this endpoint to work
var dashboardActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.ServerInfoAdminAction,
),
}
// groupsActionSet contains the list of admin actions required for this endpoint to work
var groupsActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.ListGroupsAdminAction,
iampolicy.AddUserToGroupAdminAction,
//iampolicy.GetGroupAdminAction,
iampolicy.EnableGroupAdminAction,
iampolicy.DisableGroupAdminAction,
),
}
// iamPoliciesActionSet contains the list of admin actions required for this endpoint to work
var iamPoliciesActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.GetPolicyAdminAction,
iampolicy.DeletePolicyAdminAction,
iampolicy.CreatePolicyAdminAction,
iampolicy.AttachPolicyAdminAction,
iampolicy.ListUserPoliciesAdminAction,
),
}
// profilingActionSet contains the list of admin actions required for this endpoint to work
var profilingActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.ProfilingAdminAction,
),
}
// traceActionSet contains the list of admin actions required for this endpoint to work
var traceActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.TraceAdminAction,
),
}
// usersActionSet contains the list of admin actions required for this endpoint to work
var usersActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.ListUsersAdminAction,
iampolicy.CreateUserAdminAction,
iampolicy.DeleteUserAdminAction,
iampolicy.GetUserAdminAction,
iampolicy.EnableUserAdminAction,
iampolicy.DisableUserAdminAction,
),
}
// watchActionSet contains the list of admin actions required for this endpoint to work
var watchActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.ListenBucketNotificationAction,
),
}
// notificationsActionSet contains the list of admin actions required for this endpoint to work
var notificationsActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllActions,
),
actions: iampolicy.NewActionSet(
iampolicy.ListenBucketNotificationAction,
iampolicy.PutBucketNotificationAction,
iampolicy.GetBucketNotificationAction,
),
}
// bucketsActionSet contains the list of admin actions required for this endpoint to work
var bucketsActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllActions,
),
actions: iampolicy.NewActionSet(
// Read access to buckets
iampolicy.ListMultipartUploadPartsAction,
iampolicy.ListBucketMultipartUploadsAction,
iampolicy.ListBucketAction,
iampolicy.HeadBucketAction,
iampolicy.GetObjectAction,
iampolicy.GetBucketLocationAction,
// Write access to buckets
iampolicy.AbortMultipartUploadAction,
iampolicy.CreateBucketAction,
iampolicy.PutObjectAction,
iampolicy.DeleteObjectAction,
iampolicy.DeleteBucketAction,
// Assign bucket policies
iampolicy.PutBucketPolicyAction,
iampolicy.DeleteBucketPolicyAction,
iampolicy.GetBucketPolicyAction,
),
}
// serviceAccountsActionSet no actions needed for this module to work
var serviceAccountsActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(),
actions: iampolicy.NewActionSet(),
}
// tenantsActionSet temporally no actions needed for tenants sections to work
var tenantsActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(),
actions: iampolicy.NewActionSet(),
}
// healActionSet contains the list of admin actions required for this endpoint to work
var healActionSet = ConfigurationActionSet{
actionTypes: iampolicy.NewActionSet(
iampolicy.AllAdminActions,
),
actions: iampolicy.NewActionSet(
iampolicy.HealAdminAction,
),
}
// endpointRules contains the mapping between endpoints and ActionSets, additional rules can be added here
var endpointRules = map[string]ConfigurationActionSet{
configuration: configurationActionSet,
users: usersActionSet,
groups: groupsActionSet,
iamPolicies: iamPoliciesActionSet,
dashboard: dashboardActionSet,
profiling: profilingActionSet,
trace: traceActionSet,
logs: logsActionSet,
watch: watchActionSet,
notifications: notificationsActionSet,
buckets: bucketsActionSet,
bucketsDetail: bucketsActionSet,
serviceAccounts: serviceAccountsActionSet,
heal: healActionSet,
}
// operatorRules contains the mapping between endpoints and ActionSets for operator only mode
var operatorRules = map[string]ConfigurationActionSet{
tenants: tenantsActionSet,
tenantsDetail: tenantsActionSet,
}
// operatorOnly ENV variable
var operatorOnly = GetOperatorMode()
// GetActionsStringFromPolicy extract the admin/s3 actions from a given policy and return them in []string format
//
// ie:
// {
// "Version": "2012-10-17",
// "Statement": [{
// "Action": [
// "admin:ServerInfo",
// "admin:CreatePolicy",
// "admin:GetUser"
// ],
// ...
// },
// {
// "Action": [
// "s3:ListenBucketNotification",
// "s3:PutBucketNotification"
// ],
// ...
// }
// ]
// }
// Will produce an array like: ["admin:ServerInfo", "admin:CreatePolicy", "admin:GetUser", "s3:ListenBucketNotification", "s3:PutBucketNotification"]\
func GetActionsStringFromPolicy(policy *iampolicy.Policy) []string {
var actions []string
for _, statement := range policy.Statements {
// We only care about allowed actions
if statement.Effect.IsAllowed(true) {
for _, action := range statement.Actions.ToSlice() {
actions = append(actions, string(action))
}
}
}
return actions
}
// actionsStringToActionSet convert a given string array to iampolicy.ActionSet structure
// this avoids ending with duplicate actions
func actionsStringToActionSet(actions []string) iampolicy.ActionSet {
actionsSet := iampolicy.ActionSet{}
for _, action := range actions {
actionsSet.Add(iampolicy.Action(action))
}
return actionsSet
}
// GetAuthorizedEndpoints return a list of allowed endpoint based on a provided *iampolicy.Policy
// ie: pages the user should have access based on his current privileges
func GetAuthorizedEndpoints(actions []string) []string {
rangeTake := endpointRules
if operatorOnly {
rangeTake = operatorRules
}
if len(actions) == 0 {
return []string{}
}
// Prepare new ActionSet structure that will hold all the user actions
userAllowedAction := actionsStringToActionSet(actions)
allowedEndpoints := []string{}
for endpoint, rules := range rangeTake {
// check if user policy matches s3:* or admin:* typesIntersection
endpointActionTypes := rules.actionTypes
typesIntersection := endpointActionTypes.Intersection(userAllowedAction)
if len(typesIntersection) == len(endpointActionTypes.ToSlice()) {
allowedEndpoints = append(allowedEndpoints, endpoint)
continue
}
// check if user policy matches explicitly defined endpoint required actions
endpointRequiredActions := rules.actions
actionsIntersection := endpointRequiredActions.Intersection(userAllowedAction)
if len(actionsIntersection) == len(endpointRequiredActions.ToSlice()) {
allowedEndpoints = append(allowedEndpoints, endpoint)
}
}
return allowedEndpoints
}

190
pkg/acl/endpoints_test.go Normal file
View File

@@ -0,0 +1,190 @@
// This file is part of MinIO Orchestrator
// 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 <http://www.gnu.org/licenses/>.
package acl
import (
"reflect"
"testing"
iampolicy "github.com/minio/minio/pkg/iam/policy"
)
type args struct {
actions []string
}
type endpoint struct {
name string
args args
want int
}
func validateEndpoints(t *testing.T, configs []endpoint) {
for _, tt := range configs {
t.Run(tt.name, func(t *testing.T) {
if got := GetAuthorizedEndpoints(tt.args.actions); !reflect.DeepEqual(len(got), tt.want) {
t.Errorf("GetAuthorizedEndpoints() = %v, want %v", len(got), tt.want)
}
})
}
}
func TestGetAuthorizedEndpoints(t *testing.T) {
tests := []endpoint{
{
name: "dashboard endpoint",
args: args{
[]string{"admin:ServerInfo"},
},
want: 2,
},
{
name: "policies endpoint",
args: args{
[]string{
"admin:CreatePolicy",
"admin:DeletePolicy",
"admin:GetPolicy",
"admin:AttachUserOrGroupPolicy",
"admin:ListUserPolicies",
},
},
want: 2,
},
{
name: "all admin endpoints",
args: args{
[]string{
"admin:*",
},
},
want: 11,
},
{
name: "all s3 endpoints",
args: args{
[]string{
"s3:*",
},
},
want: 4,
},
{
name: "all admin and s3 endpoints",
args: args{
[]string{
"admin:*",
"s3:*",
},
},
want: 14,
},
{
name: "no endpoints",
args: args{
[]string{},
},
want: 0,
},
}
validateEndpoints(t, tests)
}
func TestOperatorOnlyEndpoints(t *testing.T) {
operatorOnly = true
tests := []endpoint{
{
name: "Operator Only - all admin endpoints",
args: args{
[]string{
"admin:*",
},
},
want: 2,
},
{
name: "Operator Only - all s3 endpoints",
args: args{
[]string{
"s3:*",
},
},
want: 2,
},
{
name: "Operator Only - all admin and s3 endpoints",
args: args{
[]string{
"admin:*",
"s3:*",
},
},
want: 2,
},
{
name: "Operator Only - no endpoints",
args: args{
[]string{},
},
want: 0,
},
}
validateEndpoints(t, tests)
}
func TestGetActionsStringFromPolicy(t *testing.T) {
type args struct {
policy *iampolicy.Policy
}
tests := []struct {
name string
args args
want int
}{
{
name: "parse ReadOnly policy",
args: args{
policy: &iampolicy.ReadOnly,
},
want: 2,
},
{
name: "parse WriteOnly policy",
args: args{
policy: &iampolicy.WriteOnly,
},
want: 1,
},
{
name: "parse AdminDiagnostics policy",
args: args{
policy: &iampolicy.AdminDiagnostics,
},
want: 6,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetActionsStringFromPolicy(tt.args.policy); !reflect.DeepEqual(len(got), tt.want) {
t.Errorf("GetActionsStringFromPolicy() = %v, want %v", len(got), tt.want)
}
})
}
}

View File

@@ -0,0 +1,21 @@
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package,register
// Package v1beta1 is v1beta1 version of the API.
// +groupName=networking.gke.io
package v1beta1

View File

@@ -0,0 +1,56 @@
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: "networking.gke.io", Version: "v1beta1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// SchemeBuilder points to a list of functions added to Scheme.
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
// AddToScheme applies all stored functions to Scheme.
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
}
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&ManagedCertificate{},
&ManagedCertificateList{},
)
v1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@@ -0,0 +1,87 @@
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ManagedCertificateList is a list of ManagedCertificate objects.
type ManagedCertificateList struct {
metav1.TypeMeta `json:",inline"`
// metdata is the standard list metadata.
// +optional
metav1.ListMeta `json:"metadata" protobuf:"bytes,1,opt,name=metadata"`
// items is the list of managed certificate objects.
Items []ManagedCertificate `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ManagedCertificate configures the domains for which client requests a managed certificate. It also provides the current status of the certficate.
type ManagedCertificate struct {
metav1.TypeMeta `json:",inline"`
// Standard object metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Specification of the managed certificate.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status.
// +optional
Spec ManagedCertificateSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Current information about the managed certificate.
// +optional
Status ManagedCertificateStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// ManagedCertificateSpec configures the domains for which client requests a managed certificate.
type ManagedCertificateSpec struct {
// Specifies a list of domains populated by the user for which he requests a managed certificate.
Domains []string `json:"domains" protobuf:"bytes,2,rep,name=domains"`
}
// ManagedCertificateStatus provides the current state of the certificate.
type ManagedCertificateStatus struct {
// Specifies the status of the managed certificate.
// +optional
CertificateStatus string `json:"certificateStatus,omitempty" protobuf:"bytes,2,opt,name=certificateStatus"`
// Specifies the status of certificate provisioning for domains selected by the user.
DomainStatus []DomainStatus `json:"domainStatus" protobuf:"bytes,3,rep,name=domainStatus"`
// Specifies the name of the provisioned managed certificate.
// +optional
CertificateName string `json:"certificateName,omitempty" protobuf:"bytes,4,opt,name=certificateName"`
// Specifies the expire time of the provisioned managed certificate.
// +optional
ExpireTime string `json:"expireTime,omitempty" protobuf:"bytes,5,opt,name=expireTime"`
}
// DomainStatus is a pair which associates domain name with status of certificate provisioning for this domain.
type DomainStatus struct {
// The domain name.
Domain string `json:"domain" protobuf:"bytes,1,name=domain"`
// The status.
Status string `json:"status" protobuf:"bytes,2,name=status"`
}

View File

@@ -0,0 +1,144 @@
// +build !ignore_autogenerated
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1beta1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DomainStatus) DeepCopyInto(out *DomainStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainStatus.
func (in *DomainStatus) DeepCopy() *DomainStatus {
if in == nil {
return nil
}
out := new(DomainStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedCertificate) DeepCopyInto(out *ManagedCertificate) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCertificate.
func (in *ManagedCertificate) DeepCopy() *ManagedCertificate {
if in == nil {
return nil
}
out := new(ManagedCertificate)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ManagedCertificate) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedCertificateList) DeepCopyInto(out *ManagedCertificateList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ManagedCertificate, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCertificateList.
func (in *ManagedCertificateList) DeepCopy() *ManagedCertificateList {
if in == nil {
return nil
}
out := new(ManagedCertificateList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ManagedCertificateList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedCertificateSpec) DeepCopyInto(out *ManagedCertificateSpec) {
*out = *in
if in.Domains != nil {
in, out := &in.Domains, &out.Domains
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCertificateSpec.
func (in *ManagedCertificateSpec) DeepCopy() *ManagedCertificateSpec {
if in == nil {
return nil
}
out := new(ManagedCertificateSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedCertificateStatus) DeepCopyInto(out *ManagedCertificateStatus) {
*out = *in
if in.DomainStatus != nil {
in, out := &in.DomainStatus, &out.DomainStatus
*out = make([]DomainStatus, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCertificateStatus.
func (in *ManagedCertificateStatus) DeepCopy() *ManagedCertificateStatus {
if in == nil {
return nil
}
out := new(ManagedCertificateStatus)
in.DeepCopyInto(out)
return out
}

View File

@@ -0,0 +1,21 @@
/*
Copyright 2019 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package,register
// Package v1beta2 is v1beta2 version of the API.
// +groupName=networking.gke.io
package v1beta2

View File

@@ -0,0 +1,56 @@
/*
Copyright 2019 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta2
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: "networking.gke.io", Version: "v1beta2"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// SchemeBuilder points to a list of functions added to Scheme.
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
// AddToScheme applies all stored functions to Scheme.
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
}
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&ManagedCertificate{},
&ManagedCertificateList{},
)
v1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@@ -0,0 +1,87 @@
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ManagedCertificateList is a list of ManagedCertificate objects.
type ManagedCertificateList struct {
metav1.TypeMeta `json:",inline"`
// metdata is the standard list metadata.
// +optional
metav1.ListMeta `json:"metadata" protobuf:"bytes,1,opt,name=metadata"`
// items is the list of managed certificate objects.
Items []ManagedCertificate `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ManagedCertificate configures the domains for which client requests a managed certificate. It also provides the current status of the certficate.
type ManagedCertificate struct {
metav1.TypeMeta `json:",inline"`
// Standard object metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Specification of the managed certificate.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status.
// +optional
Spec ManagedCertificateSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Current information about the managed certificate.
// +optional
Status ManagedCertificateStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// ManagedCertificateSpec configures the domains for which client requests a managed certificate.
type ManagedCertificateSpec struct {
// Specifies a list of domains populated by the user for which he requests a managed certificate.
Domains []string `json:"domains" protobuf:"bytes,2,rep,name=domains"`
}
// ManagedCertificateStatus provides the current state of the certificate.
type ManagedCertificateStatus struct {
// Specifies the status of the managed certificate.
// +optional
CertificateStatus string `json:"certificateStatus,omitempty" protobuf:"bytes,2,opt,name=certificateStatus"`
// Specifies the status of certificate provisioning for domains selected by the user.
DomainStatus []DomainStatus `json:"domainStatus" protobuf:"bytes,3,rep,name=domainStatus"`
// Specifies the name of the provisioned managed certificate.
// +optional
CertificateName string `json:"certificateName,omitempty" protobuf:"bytes,4,opt,name=certificateName"`
// Specifies the expire time of the provisioned managed certificate.
// +optional
ExpireTime string `json:"expireTime,omitempty" protobuf:"bytes,5,opt,name=expireTime"`
}
// DomainStatus is a pair which associates domain name with status of certificate provisioning for this domain.
type DomainStatus struct {
// The domain name.
Domain string `json:"domain" protobuf:"bytes,1,name=domain"`
// The status.
Status string `json:"status" protobuf:"bytes,2,name=status"`
}

View File

@@ -0,0 +1,144 @@
// +build !ignore_autogenerated
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1beta2
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DomainStatus) DeepCopyInto(out *DomainStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainStatus.
func (in *DomainStatus) DeepCopy() *DomainStatus {
if in == nil {
return nil
}
out := new(DomainStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedCertificate) DeepCopyInto(out *ManagedCertificate) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCertificate.
func (in *ManagedCertificate) DeepCopy() *ManagedCertificate {
if in == nil {
return nil
}
out := new(ManagedCertificate)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ManagedCertificate) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedCertificateList) DeepCopyInto(out *ManagedCertificateList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ManagedCertificate, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCertificateList.
func (in *ManagedCertificateList) DeepCopy() *ManagedCertificateList {
if in == nil {
return nil
}
out := new(ManagedCertificateList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ManagedCertificateList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedCertificateSpec) DeepCopyInto(out *ManagedCertificateSpec) {
*out = *in
if in.Domains != nil {
in, out := &in.Domains, &out.Domains
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCertificateSpec.
func (in *ManagedCertificateSpec) DeepCopy() *ManagedCertificateSpec {
if in == nil {
return nil
}
out := new(ManagedCertificateSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedCertificateStatus) DeepCopyInto(out *ManagedCertificateStatus) {
*out = *in
if in.DomainStatus != nil {
in, out := &in.DomainStatus, &out.DomainStatus
*out = make([]DomainStatus, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCertificateStatus.
func (in *ManagedCertificateStatus) DeepCopy() *ManagedCertificateStatus {
if in == nil {
return nil
}
out := new(ManagedCertificateStatus)
in.DeepCopyInto(out)
return out
}

49
pkg/auth/idp.go Normal file
View File

@@ -0,0 +1,49 @@
// 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 <http://www.gnu.org/licenses/>.
package auth
import (
"context"
"github.com/minio/mcs/pkg/auth/idp/oauth2"
)
// IdentityProviderClient interface with all functions to be implemented
// by mock when testing, it should include all IdentityProviderClient respective api calls
// that are used within this project.
type IdentityProviderClient interface {
VerifyIdentity(ctx context.Context, code, state string) (*oauth2.User, error)
GenerateLoginURL() string
}
// Interface implementation
//
// Define the structure of a IdentityProvider Client and define the functions that are actually used
// during the authentication flow.
type IdentityProvider struct {
Client IdentityProviderClient
}
// VerifyIdentity will verify the user identity against the idp using the authorization code flow
func (c IdentityProvider) VerifyIdentity(ctx context.Context, code, state string) (*oauth2.User, error) {
return c.Client.VerifyIdentity(ctx, code, state)
}
// GenerateLoginURL returns a new URL used by the user to login against the idp
func (c IdentityProvider) GenerateLoginURL() string {
return c.Client.GenerateLoginURL()
}

View File

@@ -0,0 +1,71 @@
// 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 <http://www.gnu.org/licenses/>.
// Package oauth2 contains all the necessary configurations to initialize the
// idp communication using oauth2 protocol
package oauth2
import (
"github.com/minio/mcs/pkg/auth/utils"
"github.com/minio/minio/pkg/env"
)
func GetIdpURL() string {
return env.Get(McsIdpURL, "")
}
func GetIdpClientID() string {
return env.Get(McsIdpClientID, "")
}
func GetIdpSecret() string {
return env.Get(McsIdpSecret, "")
}
// Public endpoint used by the identity oidcProvider when redirecting the user after identity verification
func GetIdpCallbackURL() string {
return env.Get(McsIdpCallbackURL, "")
}
func GetIdpAdminRoles() string {
return env.Get(McsIdpAdminRoles, "")
}
func IsIdpEnabled() bool {
return GetIdpURL() != "" &&
GetIdpClientID() != "" &&
GetIdpSecret() != "" &&
GetIdpCallbackURL() != ""
}
var defaultPassphraseForIdpHmac = utils.RandomCharString(64)
// GetPassphraseForIdpHmac returns passphrase for the pbkdf2 function used to sign the oauth2 state parameter
func getPassphraseForIdpHmac() string {
return env.Get(McsIdpHmacPassphrase, defaultPassphraseForIdpHmac)
}
var defaultSaltForIdpHmac = utils.RandomCharString(64)
// GetSaltForIdpHmac returns salt for the pbkdf2 function used to sign the oauth2 state parameter
func getSaltForIdpHmac() string {
return env.Get(McsIdpHmacSalt, defaultSaltForIdpHmac)
}
// GetSaltForIdpHmac returns the policy to be assigned to the users authenticating via an IDP
func GetIDPPolicyForUser() string {
return env.Get(McsIdpPolicyUser, "mcsAdmin")
}

View File

@@ -0,0 +1,29 @@
// 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 <http://www.gnu.org/licenses/>.
package oauth2
const (
// const for idp configuration
McsIdpURL = "MCS_IDP_URL"
McsIdpClientID = "MCS_IDP_CLIENT_ID"
McsIdpSecret = "MCS_IDP_SECRET"
McsIdpCallbackURL = "MCS_IDP_CALLBACK"
McsIdpAdminRoles = "MCS_IDP_ADMIN_ROLES"
McsIdpHmacPassphrase = "MCS_IDP_HMAC_PASSPHRASE"
McsIdpHmacSalt = "MCS_IDP_HMAC_SALT"
McsIdpPolicyUser = "MCS_IDP_POLICY_USER"
)

View File

@@ -0,0 +1,229 @@
// 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 <http://www.gnu.org/licenses/>.
package oauth2
import (
"context"
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"log"
"net/http"
"net/url"
"strings"
"github.com/coreos/go-oidc"
"github.com/minio/mcs/pkg/auth/utils"
"golang.org/x/crypto/pbkdf2"
xoauth2 "golang.org/x/oauth2"
)
var (
errGeneric = errors.New("an error occurred, please try again")
)
type Configuration interface {
Exchange(ctx context.Context, code string, opts ...xoauth2.AuthCodeOption) (*xoauth2.Token, error)
AuthCodeURL(state string, opts ...xoauth2.AuthCodeOption) string
PasswordCredentialsToken(ctx context.Context, username string, password string) (*xoauth2.Token, error)
Client(ctx context.Context, t *xoauth2.Token) *http.Client
TokenSource(ctx context.Context, t *xoauth2.Token) xoauth2.TokenSource
}
type Config struct {
xoauth2.Config
}
func (ac Config) Exchange(ctx context.Context, code string, opts ...xoauth2.AuthCodeOption) (*xoauth2.Token, error) {
return ac.Exchange(ctx, code, opts...)
}
func (ac Config) AuthCodeURL(state string, opts ...xoauth2.AuthCodeOption) string {
return ac.AuthCodeURL(state, opts...)
}
func (ac Config) PasswordCredentialsToken(ctx context.Context, username string, password string) (*xoauth2.Token, error) {
return ac.PasswordCredentialsToken(ctx, username, password)
}
func (ac Config) Client(ctx context.Context, t *xoauth2.Token) *http.Client {
return ac.Client(ctx, t)
}
func (ac Config) TokenSource(ctx context.Context, t *xoauth2.Token) xoauth2.TokenSource {
return ac.TokenSource(ctx, t)
}
// Provider is a wrapper of the oauth2 configuration and the oidc provider
type Provider struct {
// oauth2Config is an interface configuration that contains the following fields
// Config{
// ClientID string
// ClientSecret string
// RedirectURL string
// Endpoint oauth2.Endpoint
// Scopes []string
// }
// - ClientID is the public identifier for this application
// - ClientSecret is a shared secret between this application and the authorization server
// - RedirectURL is the URL to redirect users going through
// the OAuth flow, after the resource owner's URLs.
// - Endpoint contains the resource server's token endpoint
// URLs. These are constants specific to each server and are
// often available via site-specific packages, such as
// google.Endpoint or github.Endpoint.
// - Scopes specifies optional requested permissions.
ClientID string
oauth2Config Configuration
oidcProvider *oidc.Provider
}
// derivedKey is the key used to compute the HMAC for signing the oauth state parameter
// its derived using pbkdf on MCS_IDP_HMAC_PASSPHRASE with MCS_IDP_HMAC_SALT
var derivedKey = pbkdf2.Key([]byte(getPassphraseForIdpHmac()), []byte(getSaltForIdpHmac()), 4096, 32, sha1.New)
// NewOauth2ProviderClient instantiates a new oauth2 client using the configured credentials
// it returns a *Provider object that contains the necessary configuration to initiate an
// oauth2 authentication flow
func NewOauth2ProviderClient(ctx context.Context, scopes []string) (*Provider, error) {
provider, err := oidc.NewProvider(ctx, GetIdpURL())
if err != nil {
return nil, err
}
// If provided scopes are empty we use a default list
if len(scopes) == 0 {
scopes = []string{oidc.ScopeOpenID, "profile", "app_metadata", "user_metadata", "email"}
}
client := new(Provider)
config := xoauth2.Config{
ClientID: GetIdpClientID(),
ClientSecret: GetIdpSecret(),
RedirectURL: GetIdpCallbackURL(),
Endpoint: provider.Endpoint(),
Scopes: scopes,
}
client.oauth2Config = &config
client.oidcProvider = provider
client.ClientID = GetIdpClientID()
return client, nil
}
type User struct {
AppMetadata map[string]interface{} `json:"app_metadata"`
Blocked bool `json:"blocked"`
CreatedAt string `json:"created_at"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
FamilyName string `json:"family_name"`
GivenName string `json:"given_name"`
Identities []interface{} `json:"identities"`
LastIP string `json:"last_ip"`
LastLogin string `json:"last_login"`
LastPasswordReset string `json:"last_password_reset"`
LoginsCount int `json:"logins_count"`
Mltifactor string `json:"multifactor"`
Name string `json:"name"`
Nickname string `json:"nickname"`
PhoneNumber string `json:"phone_number"`
PhoneVerified bool `json:"phone_verified"`
Picture string `json:"picture"`
UpdatedAt string `json:"updated_at"`
UserID string `json:"user_id"`
UserMetadata map[string]interface{} `json:"user_metadata"`
Username string `json:"username"`
}
// VerifyIdentity will contact the configured IDP and validate the user identity based on the authorization code
func (client *Provider) VerifyIdentity(ctx context.Context, code, state string) (*User, error) {
// verify the provided state is valid (prevents CSRF attacks)
if !validateOauth2State(state) {
return nil, errGeneric
}
// verify the authorization code against the identity oidcProvider
// idp will return a token in exchange
token, err := client.oauth2Config.Exchange(ctx, code)
if err != nil {
log.Println("Failed to verify authorization code", err)
return nil, errGeneric
}
// extract and check id_token field is provided in the response
rawIDToken, ok := token.Extra("id_token").(string)
if !ok {
log.Println("No id_token field in oauth2 token")
return nil, errGeneric
}
config := &oidc.Config{
ClientID: client.ClientID,
}
idToken, err := client.oidcProvider.Verifier(config).Verify(ctx, rawIDToken)
if err != nil {
log.Println("Failed to verify ID token", err)
return nil, errGeneric
}
var profile User
// Populate the profile object using the claims included in the token
if err := idToken.Claims(&profile); err != nil {
log.Println("Failed to read profile information", err)
return nil, errGeneric
}
return &profile, nil
}
// validateOauth2State validates the provided state was originated using the same
// instance (or one configured using the same secrets) of MCS, this is basically used to prevent CSRF attacks
// https://security.stackexchange.com/questions/20187/oauth2-cross-site-request-forgery-and-state-parameter
func validateOauth2State(state string) bool {
// state contains a base64 encoded string that may ends with "==", the browser encodes that to "%3D%3D"
// query unescape is need it before trying to decode the base64 string
encodedMessage, err := url.QueryUnescape(state)
if err != nil {
log.Println(err)
return false
}
// decode the state parameter value
message, err := base64.StdEncoding.DecodeString(encodedMessage)
if err != nil {
log.Println(err)
return false
}
s := strings.Split(string(message), ":")
// Validate that the decoded message has the right format "message:hmac"
if len(s) != 2 {
return false
}
// extract the state and hmac
incomingState, incomingHmac := s[0], s[1]
// validate that hmac(incomingState + pbkdf2(secret, salt)) == incomingHmac
return utils.ComputeHmac256(incomingState, derivedKey) == incomingHmac
}
// GetRandomStateWithHMAC computes message + hmac(message, pbkdf2(key, salt)) to be used as state during the oauth authorization
func GetRandomStateWithHMAC(length int) string {
state := utils.RandomCharString(length)
hmac := utils.ComputeHmac256(state, derivedKey)
return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", state, hmac)))
}
// GenerateLoginURL returns a new login URL based on the configured IDP
func (client *Provider) GenerateLoginURL() string {
// generates random state and sign it using HMAC256
state := GetRandomStateWithHMAC(25)
loginURL := client.oauth2Config.AuthCodeURL(state)
return strings.TrimSpace(loginURL)
}

View File

@@ -0,0 +1,98 @@
// 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 <http://www.gnu.org/licenses/>.
package oauth2
import (
"context"
"net/http"
"testing"
"github.com/coreos/go-oidc"
"github.com/stretchr/testify/assert"
"golang.org/x/oauth2"
)
type Oauth2configMock struct{}
var oauth2ConfigExchangeMock func(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)
var oauth2ConfigAuthCodeURLMock func(state string, opts ...oauth2.AuthCodeOption) string
var oauth2ConfigPasswordCredentialsTokenMock func(ctx context.Context, username string, password string) (*oauth2.Token, error)
var oauth2ConfigClientMock func(ctx context.Context, t *oauth2.Token) *http.Client
var oauth2ConfigokenSourceMock func(ctx context.Context, t *oauth2.Token) oauth2.TokenSource
func (ac Oauth2configMock) Exchange(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
return oauth2ConfigExchangeMock(ctx, code, opts...)
}
func (ac Oauth2configMock) AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string {
return oauth2ConfigAuthCodeURLMock(state, opts...)
}
func (ac Oauth2configMock) PasswordCredentialsToken(ctx context.Context, username string, password string) (*oauth2.Token, error) {
return oauth2ConfigPasswordCredentialsTokenMock(ctx, username, password)
}
func (ac Oauth2configMock) Client(ctx context.Context, t *oauth2.Token) *http.Client {
return oauth2ConfigClientMock(ctx, t)
}
func (ac Oauth2configMock) TokenSource(ctx context.Context, t *oauth2.Token) oauth2.TokenSource {
return oauth2ConfigokenSourceMock(ctx, t)
}
func TestGenerateLoginURL(t *testing.T) {
funcAssert := assert.New(t)
oauth2Provider := Provider{
oauth2Config: Oauth2configMock{},
oidcProvider: &oidc.Provider{},
}
// Test-1 : GenerateLoginURL() generates URL correctly with provided state
oauth2ConfigAuthCodeURLMock = func(state string, opts ...oauth2.AuthCodeOption) string {
// Internally we are testing the private method getRandomStateWithHMAC, this function should always returns
// a non-empty string
return state
}
url := oauth2Provider.GenerateLoginURL()
funcAssert.NotEqual("", url)
}
func TestVerifyIdentity(t *testing.T) {
ctx := context.Background()
funcAssert := assert.New(t)
// mock data
oauth2Provider := Provider{
oauth2Config: Oauth2configMock{},
oidcProvider: &oidc.Provider{},
}
// Test-1 : VerifyIdentity() should fail because of bad state token
_, err := oauth2Provider.VerifyIdentity(ctx, "AAABBBCCCDDDEEEFFF", "badtoken")
funcAssert.NotNil(err)
// Test-2 : VerifyIdentity() should fail because no id_token is provided by the idp
oauth2ConfigExchangeMock = func(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
return &oauth2.Token{}, nil
}
state := GetRandomStateWithHMAC(32)
code := "AAABBBCCCDDDEEEFFF"
_, err = oauth2Provider.VerifyIdentity(ctx, code, state)
funcAssert.NotNil(err)
// Test-3 : VerifyIdentity() should fail because no id_token is provided by the idp
// TODO
// Test-4 : VerifyIdentity() should fail because oidcProvider.Verifier returned an error
// TODO
// Test-5 : VerifyIdentity() should fail because idToken.Claims contains invalid fields
// TODO
}

231
pkg/auth/jwt.go Normal file
View File

@@ -0,0 +1,231 @@
// 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 <http://www.gnu.org/licenses/>.
package auth
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"io"
"log"
"net/http"
"strings"
"time"
jwtgo "github.com/dgrijalva/jwt-go"
"github.com/go-openapi/swag"
"github.com/minio/mcs/models"
xjwt "github.com/minio/mcs/pkg/auth/jwt"
"github.com/minio/minio-go/v6/pkg/credentials"
uuid "github.com/satori/go.uuid"
"golang.org/x/crypto/pbkdf2"
)
var (
errAuthentication = errors.New("authentication failed, check your access credentials")
errNoAuthToken = errors.New("JWT token missing")
errReadingToken = errors.New("JWT internal data is malformed")
errClaimsFormat = errors.New("encrypted jwt claims not in the right format")
)
// derivedKey is the key used to encrypt the JWT claims, its derived using pbkdf on MCS_PBKDF_PASSPHRASE with MCS_PBKDF_SALT
var derivedKey = pbkdf2.Key([]byte(xjwt.GetPBKDFPassphrase()), []byte(xjwt.GetPBKDFSalt()), 4096, 32, sha1.New)
// IsJWTValid returns true or false depending if the provided jwt is valid or not
func IsJWTValid(token string) bool {
_, err := JWTAuthenticate(token)
return err == nil
}
// DecryptedClaims claims struct for decrypted credentials
type DecryptedClaims struct {
AccessKeyID string
SecretAccessKey string
SessionToken string
Actions []string
}
// JWTAuthenticate takes a jwt, decode it, extract claims and validate the signature
// if the jwt claims.Data is valid we proceed to decrypt the information inside
//
// returns claims after validation in the following format:
//
// type DecryptedClaims struct {
// AccessKeyID
// SecretAccessKey
// SessionToken
// }
func JWTAuthenticate(token string) (*DecryptedClaims, error) {
if token == "" {
return nil, errNoAuthToken
}
// initialize claims object
claims := xjwt.NewMapClaims()
// populate the claims object
if err := xjwt.ParseWithClaims(token, claims); err != nil {
return nil, errAuthentication
}
// decrypt the claims.Data field
claimTokens, err := decryptClaims(claims.Data)
if err != nil {
// we print decryption token error information for debugging purposes
log.Println(err)
// we return a generic error that doesn't give any information to attackers
return nil, errReadingToken
}
// claimsTokens contains the decrypted STS claims
return claimTokens, nil
}
// NewJWTWithClaimsForClient generates a new jwt with claims based on the provided STS credentials, first
// encrypts the claims and the sign them
func NewJWTWithClaimsForClient(credentials *credentials.Value, actions []string, audience string) (string, error) {
if credentials != nil {
encryptedClaims, err := encryptClaims(credentials.AccessKeyID, credentials.SecretAccessKey, credentials.SessionToken, actions)
if err != nil {
return "", err
}
claims := xjwt.NewStandardClaims()
claims.SetExpiry(time.Now().UTC().Add(xjwt.GetMcsSTSAndJWTDurationTime()))
claims.SetSubject(uuid.NewV4().String())
claims.SetData(encryptedClaims)
claims.SetAudience(audience)
jwt := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, claims)
return jwt.SignedString([]byte(xjwt.GetHmacJWTSecret()))
}
return "", errors.New("provided credentials are empty")
}
// encryptClaims() receives the 3 STS claims, concatenate them and encrypt them using AES-GCM
// returns a base64 encoded ciphertext
func encryptClaims(accessKeyID, secretAccessKey, sessionToken string, actions []string) (string, error) {
payload := []byte(fmt.Sprintf("%s#%s#%s#%s", accessKeyID, secretAccessKey, sessionToken, strings.Join(actions, ",")))
ciphertext, err := encrypt(payload)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
// decryptClaims() receives base64 encoded ciphertext, decode it, decrypt it (AES-GCM) and produces a *DecryptedClaims object
func decryptClaims(ciphertext string) (*DecryptedClaims, error) {
decoded, err := base64.StdEncoding.DecodeString(ciphertext)
if err != nil {
log.Println(err)
return nil, errClaimsFormat
}
plaintext, err := decrypt(decoded)
if err != nil {
log.Println(err)
return nil, errClaimsFormat
}
s := strings.Split(string(plaintext), "#")
// Validate that the decrypted string has the right format "accessKeyID:secretAccessKey:sessionToken"
if len(s) != 4 {
return nil, errClaimsFormat
}
accessKeyID, secretAccessKey, sessionToken, actions := s[0], s[1], s[2], s[3]
actionsList := strings.Split(actions, ",")
return &DecryptedClaims{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
SessionToken: sessionToken,
Actions: actionsList,
}, nil
}
// Encrypt a blob of data using AEAD (AES-GCM) with a pbkdf2 derived key
func encrypt(plaintext []byte) ([]byte, error) {
block, _ := aes.NewCipher(derivedKey)
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}
cipherText := gcm.Seal(nonce, nonce, plaintext, nil)
return cipherText, nil
}
// Decrypts a blob of data using AEAD (AES-GCM) with a pbkdf2 derived key
func decrypt(data []byte) ([]byte, error) {
block, err := aes.NewCipher(derivedKey)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
nonce, cipherText := data[:nonceSize], data[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, cipherText, nil)
if err != nil {
return nil, err
}
return plaintext, nil
}
// GetTokenFromRequest returns a token from a http Request
// either defined on a cookie `token` or on Authorization header.
//
// Authorization Header needs to be like "Authorization Bearer <jwt_token>"
func GetTokenFromRequest(r *http.Request) (*string, error) {
// Get Auth token
var reqToken string
// Token might come either as a Cookie or as a Header
// if not set in cookie, check if it is set on Header.
tokenCookie, err := r.Cookie("token")
if err != nil {
headerToken := r.Header.Get("Authorization")
// reqToken should come as "Bearer <token>"
splitHeaderToken := strings.Split(headerToken, "Bearer")
if len(splitHeaderToken) <= 1 {
return nil, errNoAuthToken
}
reqToken = strings.TrimSpace(splitHeaderToken[1])
} else {
reqToken = strings.TrimSpace(tokenCookie.Value)
}
return swag.String(reqToken), nil
}
func GetClaimsFromTokenInRequest(req *http.Request) (*models.Principal, error) {
sessionID, err := GetTokenFromRequest(req)
if err != nil {
return nil, err
}
// Perform decryption of the JWT, if MCS is able to decrypt the JWT that means a valid session
// was used in the first place to get it
claims, err := JWTAuthenticate(*sessionID)
if err != nil {
return nil, err
}
return &models.Principal{
AccessKeyID: claims.AccessKeyID,
Actions: claims.Actions,
SecretAccessKey: claims.SecretAccessKey,
SessionToken: claims.SessionToken,
}, nil
}

Some files were not shown because too many files have changed in this diff Show More