Compare commits
120 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
769c8caa71 | ||
|
|
bc8429bd6b | ||
|
|
3ac64b3848 | ||
|
|
4a5be810ce | ||
|
|
e6a3bd5af5 | ||
|
|
28ac29c178 | ||
|
|
76f7c540c1 | ||
|
|
44551ac292 | ||
|
|
697bc4cd1d | ||
|
|
93e1168141 | ||
|
|
328133d3ff | ||
|
|
8a74b795c8 | ||
|
|
b7614b66d2 | ||
|
|
be069eddd5 | ||
|
|
59a5c9dbf0 | ||
|
|
1e7f272a67 | ||
|
|
1aec2d879e | ||
|
|
f77770bb6e | ||
|
|
34ff3d7157 | ||
|
|
4b6700d4ac | ||
|
|
f2c8f15fbf | ||
|
|
991204cd46 | ||
|
|
4bac7040a1 | ||
|
|
a247bf6a0c | ||
|
|
f4d08a7502 | ||
|
|
fb59e8c353 | ||
|
|
6e6ed300b7 | ||
|
|
48e6b1bb7c | ||
|
|
8949fbe245 | ||
|
|
d8e6bd7f4a | ||
|
|
4edfeb22c6 | ||
|
|
2d5d0d16ca | ||
|
|
16f8ee485a | ||
|
|
2d28f8bf35 | ||
|
|
8af3665ae2 | ||
|
|
0fa1d4bf7c | ||
|
|
8139416323 | ||
|
|
be5cd7f148 | ||
|
|
fa068b6d4a | ||
|
|
a805a49662 | ||
|
|
296e4ff5ce | ||
|
|
20749d2eae | ||
|
|
ff4e959d11 | ||
|
|
37195fefa8 | ||
|
|
13ef83cee4 | ||
|
|
b89b2d0c6a | ||
|
|
edf687fd8a | ||
|
|
cb60eba373 | ||
|
|
c49a7bbe3c | ||
|
|
3bb317535c | ||
|
|
989e6f3471 | ||
|
|
35d575e7ac | ||
|
|
92a8aab07d | ||
|
|
c5b2419191 | ||
|
|
732e0ef683 | ||
|
|
e8491d80cb | ||
|
|
35c3b53a23 | ||
|
|
6fef30f29d | ||
|
|
acf480fd25 | ||
|
|
8bbc4f0192 | ||
|
|
48e7991f11 | ||
|
|
5e9b0652b0 | ||
|
|
438211199d | ||
|
|
0f77a32656 | ||
|
|
9f3e99ede8 | ||
|
|
a8c07c0969 | ||
|
|
cf8472b04c | ||
|
|
317a7ebbd3 | ||
|
|
63f4150232 | ||
|
|
3bfc2556fc | ||
|
|
511cc47d2b | ||
|
|
9660650f41 | ||
|
|
9ac754d4de | ||
|
|
646318e1f6 | ||
|
|
beb1ac7d04 | ||
|
|
f3a9311374 | ||
|
|
44d8e9b975 | ||
|
|
f3d7e61ddb | ||
|
|
526c0f4796 | ||
|
|
fe1acaa4b6 | ||
|
|
8e9bd8728a | ||
|
|
9df9309c66 | ||
|
|
b85712e29e | ||
|
|
c32df86c76 | ||
|
|
0f52136fd2 | ||
|
|
605b80037a | ||
|
|
63b430e354 | ||
|
|
d9c212fe2f | ||
|
|
5fa0a0fca8 | ||
|
|
068ac281ea | ||
|
|
0bcf88eb7c | ||
|
|
5c137a8678 | ||
|
|
540ff31784 | ||
|
|
82ea3c1ac4 | ||
|
|
e1f177257a | ||
|
|
0211827c74 | ||
|
|
ac5732970c | ||
|
|
1b1ed55252 | ||
|
|
5c5e84b289 | ||
|
|
5755b98b66 | ||
|
|
86ee1eea6d | ||
|
|
adcbf61049 | ||
|
|
e197399441 | ||
|
|
ff2438a877 | ||
|
|
c85067dfba | ||
|
|
b1df170d80 | ||
|
|
9566f6e579 | ||
|
|
12a682e9f6 | ||
|
|
e0bb098e47 | ||
|
|
b390ce309a | ||
|
|
3dac86d3ce | ||
|
|
2001ab6dae | ||
|
|
31f0655ff6 | ||
|
|
775874cf86 | ||
|
|
9ca4daa906 | ||
|
|
2318a8a82b | ||
|
|
69ed6f5ca4 | ||
|
|
3a96e6d7e7 | ||
|
|
9a2b10476c | ||
|
|
c8938dc131 |
@@ -1,5 +1,6 @@
|
||||
node_modules/
|
||||
dist/
|
||||
target/
|
||||
mcs
|
||||
!mcs/
|
||||
console
|
||||
!console/
|
||||
portal-ui/node_modules/
|
||||
|
||||
52
.github/workflows/codeql.yml
vendored
Normal file
52
.github/workflows/codeql.yml
vendored
Normal 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
|
||||
14
.github/workflows/go.yml
vendored
14
.github/workflows/go.yml
vendored
@@ -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 mcs
|
||||
make verifiers
|
||||
make test
|
||||
make console
|
||||
|
||||
48
.github/workflows/release.yml
vendored
48
.github/workflows/release.yml
vendored
@@ -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
|
||||
14
.gitignore
vendored
14
.gitignore
vendored
@@ -6,6 +6,7 @@
|
||||
*.dylib
|
||||
.DS_Store
|
||||
*.swp
|
||||
*.orig
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
@@ -18,7 +19,16 @@ vendor/
|
||||
|
||||
# Ignore executables
|
||||
target/
|
||||
mcs
|
||||
!mcs/
|
||||
console
|
||||
!console/
|
||||
|
||||
dist/
|
||||
|
||||
# Ignore tls cert and key
|
||||
private.key
|
||||
public.crt
|
||||
|
||||
# Ignore VsCode files
|
||||
.vscode/
|
||||
*.code-workspace
|
||||
*~
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This is an example goreleaser.yaml file with some sane defaults.
|
||||
# Make sure to check the documentation at http://goreleaser.com
|
||||
project_name: mcs
|
||||
project_name: console
|
||||
|
||||
before:
|
||||
hooks:
|
||||
@@ -18,12 +18,12 @@ builds:
|
||||
- arm64
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
main: ./cmd/mcs/
|
||||
main: ./cmd/console/
|
||||
flags:
|
||||
- -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/console/pkg.ReleaseTag={{.Tag}} -X github.com/minio/console/pkg.CommitID={{.FullCommit}} -X github.com/minio/console/pkg.Version={{.Version}} -X github.com/minio/console/pkg.ShortCommitID={{.ShortCommit}} -X github.com/minio/console/pkg.ReleaseTime={{.Date}}
|
||||
archives:
|
||||
-
|
||||
replacements:
|
||||
@@ -51,7 +51,7 @@ changelog:
|
||||
nfpms:
|
||||
-
|
||||
vendor: MinIO Inc.
|
||||
homepage: https://github.com/minio/mcs
|
||||
homepage: https://github.com/minio/console
|
||||
maintainer: MinIO <minio@minio.io>
|
||||
description: MinIO Console Server
|
||||
license: GNU Affero General Public License v3.0
|
||||
@@ -71,5 +71,5 @@ dockers:
|
||||
goarch: amd64
|
||||
dockerfile: Dockerfile.release
|
||||
image_templates:
|
||||
- "minio/mcs:{{ .Tag }}"
|
||||
- "minio/mcs:latest"
|
||||
- "minio/console:{{ .Tag }}"
|
||||
- "minio/console:latest"
|
||||
|
||||
59
CONTRIBUTING.md
Normal file
59
CONTRIBUTING.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# MinIO Console Server Contribution Guide [](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_console.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 ``console`` 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 console?
|
||||
``console`` 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).
|
||||
127
DEVELOPMENT.md
Normal file
127
DEVELOPMENT.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# LDAP authentication with Console
|
||||
|
||||
## 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 consoleAdmin group (this already exists on minio and have a policy of s3::*)
|
||||
dn: cn=consoleAdmin,ou=groups,dc=example,dc=org
|
||||
objectClass: top
|
||||
objectClass: posixGroup
|
||||
gidNumber: 678
|
||||
# Assing group to new user
|
||||
dn: cn=consoleAdmin,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 consoleAdmin 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 consoleAdmin policy to user billy on MinIO
|
||||
```
|
||||
$ cat > consoleAdmin.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 consoleAdmin consoleAdmin.json
|
||||
$ mc admin policy set myminio consoleAdmin 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 Console
|
||||
|
||||
```
|
||||
export CONSOLE_ACCESS_KEY=minio
|
||||
export CONSOLE_SECRET_KEY=minio123
|
||||
...
|
||||
export CONSOLE_LDAP_ENABLED=on
|
||||
./console server
|
||||
```
|
||||
22
Dockerfile
22
Dockerfile
@@ -1,24 +1,26 @@
|
||||
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/console/go.mod
|
||||
ADD go.sum /go/src/github.com/minio/console/go.sum
|
||||
WORKDIR /go/src/github.com/minio/console/
|
||||
|
||||
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
|
||||
|
||||
ADD . /go/src/github.com/minio/mcs/
|
||||
WORKDIR /go/src/github.com/minio/mcs/
|
||||
ADD . /go/src/github.com/minio/console/
|
||||
WORKDIR /go/src/github.com/minio/console/
|
||||
|
||||
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
|
||||
RUN go build -ldflags "-w -s" -a -o console ./cmd/console
|
||||
|
||||
FROM scratch
|
||||
MAINTAINER MinIO Development "dev@min.io"
|
||||
EXPOSE 9090
|
||||
|
||||
COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=0 /go/src/github.com/minio/mcs/mcs .
|
||||
COPY --from=0 /go/src/github.com/minio/console/console .
|
||||
|
||||
CMD ["/mcs"]
|
||||
CMD ["/console"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM scratch
|
||||
MAINTAINER MinIO Development "dev@min.io"
|
||||
EXPOSE 9090
|
||||
COPY mcs /mcs
|
||||
COPY console /console
|
||||
|
||||
ENTRYPOINT ["/mcs"]
|
||||
ENTRYPOINT ["/console"]
|
||||
|
||||
63
Makefile
63
Makefile
@@ -1,23 +1,64 @@
|
||||
default: mcs
|
||||
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/console:$(VERSION)-dev"
|
||||
|
||||
.PHONY: mcs
|
||||
mcs:
|
||||
@echo "Building mcs binary to './mcs'"
|
||||
@(CGO_ENABLED=0 go build --tags=kqueue --ldflags "-s -w" -o mcs ./cmd/mcs)
|
||||
default: console
|
||||
|
||||
.PHONY: console
|
||||
console:
|
||||
@echo "Building Console binary to './console'"
|
||||
@(GO111MODULE=on CGO_ENABLED=0 go build -trimpath --tags=kqueue --ldflags "-s -w" -o console ./cmd/console)
|
||||
|
||||
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 console 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: console
|
||||
@echo "Installing console binary to '$(GOPATH)/bin/console'"
|
||||
@mkdir -p $(GOPATH)/bin && cp -f $(PWD)/console $(GOPATH)/bin/console
|
||||
@echo "Installation successful. To learn more, try \"console --help\"."
|
||||
|
||||
swagger-gen:
|
||||
@echo "Generating swagger server code from yaml"
|
||||
@swagger generate server -A mcs --main-package=mcs --exclude-main -P models.Principal -f ./swagger.yml -r NOTICE
|
||||
@rm -rf models
|
||||
@rm -rf restapi/operations
|
||||
@swagger generate server -A console --main-package=console --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/console/restapi/...)
|
||||
@(GO111MODULE=on go test -race -v github.com/minio/console/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/console/restapi/... && go tool cover -html=coverage.out && open coverage.html)
|
||||
|
||||
clean:
|
||||
@rm -vf mcs
|
||||
@echo "Cleaning up all the generated files"
|
||||
@find . -name '*.test' | xargs rm -fv
|
||||
@find . -name '*~' | xargs rm -fv
|
||||
@rm -vf console
|
||||
|
||||
docker:
|
||||
@docker build -t $(TAG) --build-arg build_version=$(BUILD_VERSION) --build-arg build_time='$(BUILD_TIME)' .
|
||||
|
||||
165
README.md
165
README.md
@@ -1,93 +1,130 @@
|
||||
# MCS Minio Console Service
|
||||
# MinIO Console
|
||||
|
||||
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 |
|
||||
| ------------- | ------------- |
|
||||
|  |  |
|
||||
|
||||
## Setup
|
||||
|
||||
All `mcs` needs is a MinIO user with admin privileges and URL pointing to your MinIO deployment.
|
||||
All `console` needs is a MinIO user with admin privileges and URL pointing to your MinIO deployment.
|
||||
> Note: We don't recommend using MinIO's Operator Credentials
|
||||
|
||||
1. Create a user for `mcs` using `mc`.
|
||||
1. Create a user for `console` using `mc`.
|
||||
```
|
||||
$ set +o history
|
||||
$ mc admin user add myminio mcs YOURMCSSECRET
|
||||
$ mc admin user add myminio console YOURCONSOLESECRET
|
||||
$ set -o history
|
||||
```
|
||||
|
||||
2. Create a policy for `mcs`
|
||||
2. Create a policy for `console` with access to everything (for testing and debugging)
|
||||
|
||||
```
|
||||
$ cat > mcsAdmin.json << EOF
|
||||
$ cat > consoleAdmin.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
|
||||
$ mc admin policy add myminio consoleAdmin consoleAdmin.json
|
||||
```
|
||||
|
||||
3. Set the policy for the new `mcs` user
|
||||
3. Set the policy for the new `console` user
|
||||
|
||||
```
|
||||
$ mc admin policy set myminio mcsAdmin user=mcs
|
||||
$ mc admin policy set myminio consoleAdmin user=console
|
||||
```
|
||||
|
||||
## Run MCS server
|
||||
|
||||
### Note
|
||||
Additionally, you can create policies to limit the privileges for `console` 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 Console server
|
||||
To run the server:
|
||||
|
||||
```
|
||||
export MCS_ACCESS_KEY=mcs
|
||||
export MCS_SECRET_KEY=YOURMCSSECRET
|
||||
export MCS_MINIO_SERVER=http://localhost:9000
|
||||
./mcs
|
||||
export CONSOLE_HMAC_JWT_SECRET=YOURJWTSIGNINGSECRET
|
||||
|
||||
#required to encrypt jwet payload
|
||||
export CONSOLE_PBKDF_PASSPHRASE=SECRET
|
||||
|
||||
#required to encrypt jwet payload
|
||||
export CONSOLE_PBKDF_SALT=SECRET
|
||||
|
||||
export CONSOLE_ACCESS_KEY=console
|
||||
export CONSOLE_SECRET_KEY=YOURCONSOLESECRET
|
||||
export CONSOLE_MINIO_SERVER=http://localhost:9000
|
||||
./console server
|
||||
```
|
||||
|
||||
## Connect Console to a Minio using TLS and a self-signed certificate
|
||||
|
||||
```
|
||||
...
|
||||
export CONSOLE_MINIO_SERVER_TLS_ROOT_CAS=<certificate_file_name>
|
||||
export CONSOLE_MINIO_SERVER=https://localhost:9000
|
||||
./console 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 console Project
|
||||
Please follow console [Contributor's Guide](https://github.com/minio/console/blob/master/CONTRIBUTING.md)
|
||||
|
||||
41
SECURITY.md
Normal file
41
SECURITY.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
We always provide security updates for the [latest release](https://github.com/minio/console/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/console](https://github,com/minio/console) (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
65
cluster/cluster.go
Normal 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/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
168
cluster/config.go
Normal 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 CONSOLE_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(ConsoleK8sAPIServer, apiServerAddress)
|
||||
}
|
||||
|
||||
// If CONSOLE_K8S_API_SERVER_TLS_ROOT_CA is true console 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(ConsoleK8SAPIServerTLSRootCA, ""))
|
||||
}
|
||||
|
||||
// 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(ConsoleNamespace, 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(ConsoleMinioImage, ""))
|
||||
// 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(ConsoleMCImage, ""))
|
||||
// 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
25
cluster/const.go
Normal 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 (
|
||||
ConsoleK8sAPIServer = "CONSOLE_K8S_API_SERVER"
|
||||
ConsoleK8SAPIServerTLSRootCA = "CONSOLE_K8S_API_SERVER_TLS_ROOT_CA"
|
||||
ConsoleMinioImage = "CONSOLE_MINIO_IMAGE"
|
||||
ConsoleMCImage = "CONSOLE_MC_IMAGE"
|
||||
ConsoleNamespace = "CONSOLE_NAMESPACE"
|
||||
)
|
||||
40
cluster/http_client.go
Normal file
40
cluster/http_client.go
Normal 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)
|
||||
}
|
||||
@@ -21,8 +21,9 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/minio/m3/mcs/pkg"
|
||||
"github.com/minio/console/pkg"
|
||||
|
||||
"github.com/minio/minio/pkg/console"
|
||||
"github.com/minio/minio/pkg/trie"
|
||||
@@ -31,8 +32,8 @@ import (
|
||||
"github.com/minio/cli"
|
||||
)
|
||||
|
||||
// Help template for m3.
|
||||
var mcsHelpTemplate = `NAME:
|
||||
// Help template for Console.
|
||||
var consoleHelpTemplate = `NAME:
|
||||
{{.Name}} - {{.Usage}}
|
||||
|
||||
DESCRIPTION:
|
||||
@@ -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 console commands currently supported are.
|
||||
var commands []cli.Command
|
||||
|
||||
// Collection of m3 commands currently supported in a trie tree.
|
||||
// Collection of console commands currently supported in a trie tree.
|
||||
commandsTree := trie.NewTrie()
|
||||
|
||||
// registerCommand registers a cli command.
|
||||
@@ -104,15 +104,17 @@ 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
|
||||
app.CustomAppHelpTemplate = consoleHelpTemplate
|
||||
app.CommandNotFound = func(ctx *cli.Context, command string) {
|
||||
console.Printf("‘%s’ is not a mcs sub-command. See ‘mcs --help’.\n", command)
|
||||
console.Printf("‘%s’ is not a console sub-command. See ‘console --help’.\n", command)
|
||||
closestCommands := findClosestCommands(command)
|
||||
if len(closestCommands) > 0 {
|
||||
console.Println()
|
||||
@@ -17,28 +17,53 @@
|
||||
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/console/restapi"
|
||||
"github.com/minio/console/restapi/operations"
|
||||
)
|
||||
|
||||
// starts the server
|
||||
var serverCmd = cli.Command{
|
||||
Name: "server",
|
||||
Aliases: []string{"srv"},
|
||||
Usage: "starts mcs server",
|
||||
Usage: "starts Console 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",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -50,7 +75,7 @@ func startServer(ctx *cli.Context) error {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
api := operations.NewMcsAPI(swaggerSpec)
|
||||
api := operations.NewConsoleAPI(swaggerSpec)
|
||||
server := restapi.NewServer(api)
|
||||
defer server.Shutdown()
|
||||
|
||||
@@ -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 console 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
80
code_of_conduct.md
Normal 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/console_operator_mode.md
Normal file
39
docs/console_operator_mode.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Running Console in Operator mode
|
||||
|
||||
`Console` will authenticate against `Kubernetes`using bearer tokens via HTTP `Authorization` header. The user will provide this token once
|
||||
in the login form, Console will validate it against Kubernetes (list apis) and if valid will generate and return a new Console 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 `Console` 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 console in your local environment and wish to make request to `Kubernetes` you can set `CONSOLE_K8S_API_SERVER`, if
|
||||
the environment variable is not present by default `Console` will use `"http://localhost:8001"`, additionally you will need to set the
|
||||
`CONSOLE_OPERATOR_MODE=on` variable to make Console 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 `CONSOLE_K8S_API_SERVER`, ie use the k8s cluster from `kubectl config view`
|
||||
|
||||
## Extract the Service account token and use it with Console
|
||||
|
||||
For local development you can use the jwt associated to the `console-sa` service account, you can get the token running
|
||||
the following command in your terminal:
|
||||
|
||||
```
|
||||
kubectl get secret $(kubectl get serviceaccount console-sa -o jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" | base64 --decode
|
||||
```
|
||||
|
||||
Then run the Console server
|
||||
|
||||
```
|
||||
CONSOLE_OPERATOR_MODE=on ./console server
|
||||
```
|
||||
37
go.mod
37
go.mod
@@ -1,21 +1,34 @@
|
||||
module github.com/minio/m3/mcs
|
||||
module github.com/minio/console
|
||||
|
||||
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.10
|
||||
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-20200725183142-90d22b271f60
|
||||
github.com/minio/minio v0.0.0-20200725154241-abbf6ce6ccf8
|
||||
github.com/minio/minio-go/v7 v7.0.2-0.20200722162308-e0105ca08252
|
||||
github.com/minio/operator v0.0.0-20200725185636-4a625e4fbb31
|
||||
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-20200709230013-948cd5f35899
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381
|
||||
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
|
||||
)
|
||||
|
||||
31
hack/update-codegen.sh
Executable file
31
hack/update-codegen.sh
Executable 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/console
|
||||
$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
BIN
images/pic1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 635 KiB |
BIN
images/pic2.png
Normal file
BIN
images/pic2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 688 KiB |
15
k8s/boilerplate.go.txt
Normal file
15
k8s/boilerplate.go.txt
Normal 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/>.
|
||||
12
k8s/console/base/console-cluster-role-binding.yaml
Normal file
12
k8s/console/base/console-cluster-role-binding.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: console-sa-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: console-sa-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: console-sa
|
||||
namespace: default
|
||||
77
k8s/console/base/console-cluster-role.yaml
Normal file
77
k8s/console/base/console-cluster-role.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: console-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:
|
||||
- minio.min.io
|
||||
resources:
|
||||
- "*"
|
||||
verbs:
|
||||
- "*"
|
||||
- apiGroups:
|
||||
- min.io
|
||||
resources:
|
||||
- "*"
|
||||
verbs:
|
||||
- "*"
|
||||
7
k8s/console/base/console-configmap.yaml
Normal file
7
k8s/console/base/console-configmap.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: console-env
|
||||
data:
|
||||
CONSOLE_PORT: "9090"
|
||||
CONSOLE_TLS_PORT: "9443"
|
||||
27
k8s/console/base/console-deployment.yaml
Normal file
27
k8s/console/base/console-deployment.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: console
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: console
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: console
|
||||
spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:latest
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
args:
|
||||
- /console
|
||||
- server
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
name: http
|
||||
- containerPort: 9433
|
||||
name: https
|
||||
5
k8s/console/base/console-service-account.yaml
Normal file
5
k8s/console/base/console-service-account.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: console-sa
|
||||
namespace: default
|
||||
14
k8s/console/base/console-service.yaml
Normal file
14
k8s/console/base/console-service.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: console
|
||||
labels:
|
||||
name: console
|
||||
spec:
|
||||
ports:
|
||||
- port: 9090
|
||||
name: http
|
||||
- port: 9443
|
||||
name: https
|
||||
selector:
|
||||
app: console
|
||||
11
k8s/console/base/kustomization.yaml
Normal file
11
k8s/console/base/kustomization.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
# beginning of customizations
|
||||
resources:
|
||||
- console-service-account.yaml
|
||||
- console-cluster-role.yaml
|
||||
- console-cluster-role-binding.yaml
|
||||
- console-configmap.yaml
|
||||
- console-service.yaml
|
||||
- console-deployment.yaml
|
||||
- minio-operator.yaml
|
||||
282
k8s/console/base/minio-operator.yaml
Normal file
282
k8s/console/base/minio-operator.yaml
Normal file
@@ -0,0 +1,282 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: minio-operator
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: tenants.minio.min.io
|
||||
spec:
|
||||
group: minio.min.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: Tenant
|
||||
singular: tenant
|
||||
plural: tenants
|
||||
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:
|
||||
metadata:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
image:
|
||||
type: string
|
||||
serviceName:
|
||||
type: string
|
||||
serviceAccountName:
|
||||
type: string
|
||||
zones:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
servers:
|
||||
type: integer
|
||||
volumesPerServer:
|
||||
type: integer
|
||||
volumeClaimTemplate:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
resources:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
nodeSelector:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
affinity:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
tolerations:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
mountPath:
|
||||
type: string
|
||||
podManagementPolicy:
|
||||
type: string
|
||||
enum: [Parallel,OrderedReady]
|
||||
default: Parallel
|
||||
requestAutoCert:
|
||||
type: boolean
|
||||
default: false
|
||||
certConfig:
|
||||
type: object
|
||||
properties:
|
||||
commonName:
|
||||
type: string
|
||||
organizationName:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
dnsNames:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
mountpath:
|
||||
type: string
|
||||
subpath:
|
||||
type: string
|
||||
nodeSelector:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
credsSecret:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
env:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
console:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
properties:
|
||||
metadata:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
image:
|
||||
type: string
|
||||
replicas:
|
||||
type: integer
|
||||
default: 2
|
||||
consoleSecret:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
resources:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
env:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
kes:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
properties:
|
||||
metadata:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
image:
|
||||
type: string
|
||||
replicas:
|
||||
type: integer
|
||||
default: 2
|
||||
kesSecret:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
liveness:
|
||||
type: object
|
||||
properties:
|
||||
initialDelaySeconds:
|
||||
type: integer
|
||||
periodSeconds:
|
||||
type: integer
|
||||
timeoutSeconds:
|
||||
type: integer
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
currentState:
|
||||
type: string
|
||||
subresources:
|
||||
# status enables the status subresource.
|
||||
status: {}
|
||||
additionalPrinterColumns:
|
||||
- name: Current State
|
||||
type: string
|
||||
jsonPath: ".status.currentState"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: minio-operator
|
||||
namespace: default
|
||||
---
|
||||
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:
|
||||
- certificates.k8s.io
|
||||
resourceNames:
|
||||
- kubernetes.io/legacy-unknown
|
||||
resources:
|
||||
- signers
|
||||
verbs:
|
||||
- approve
|
||||
- sign
|
||||
- apiGroups:
|
||||
- minio.min.io
|
||||
resources:
|
||||
- '*'
|
||||
verbs:
|
||||
- '*'
|
||||
- apiGroups:
|
||||
- min.io
|
||||
resources:
|
||||
- '*'
|
||||
verbs:
|
||||
- '*'
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
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:
|
||||
containers:
|
||||
- image: minio/k8s-operator:v3.0.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: minio-operator
|
||||
serviceAccountName: minio-operator
|
||||
44
k8s/create-kind.sh
Executable file
44
k8s/create-kind.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
# setup environment variables based on flags to see if we should build the docker containers again
|
||||
CONSOLE_DOCKER="true"
|
||||
|
||||
# evaluate flags
|
||||
# `-m` for console
|
||||
|
||||
|
||||
while getopts ":m:" opt; do
|
||||
case $opt in
|
||||
m)
|
||||
CONSOLE_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 [[ $CONSOLE_DOCKER == "true" ]]; then
|
||||
# Build mkube
|
||||
make --directory=".." k8sdev TAG=minio/console:latest
|
||||
else
|
||||
kind load docker-image minio/console:latest
|
||||
fi
|
||||
|
||||
echo "done"
|
||||
3
k8s/getoperator.sh
Executable file
3
k8s/getoperator.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
# Get's the latest deployment file from MinIO Operator
|
||||
curl https://raw.githubusercontent.com/minio/operator/master/minio-operator.yaml > operator-console/base/minio-operator.yaml
|
||||
22
k8s/kind-cluster.yaml
Normal file
22
k8s/kind-cluster.yaml
Normal 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
153
k8s/metrics-dev.yaml
Normal 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"
|
||||
12
k8s/operator-console/base/console-cluster-role-binding.yaml
Normal file
12
k8s/operator-console/base/console-cluster-role-binding.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: console-sa-binding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: console-sa-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: console-sa
|
||||
namespace: default
|
||||
77
k8s/operator-console/base/console-cluster-role.yaml
Normal file
77
k8s/operator-console/base/console-cluster-role.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: console-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:
|
||||
- minio.min.io
|
||||
resources:
|
||||
- "*"
|
||||
verbs:
|
||||
- "*"
|
||||
- apiGroups:
|
||||
- min.io
|
||||
resources:
|
||||
- "*"
|
||||
verbs:
|
||||
- "*"
|
||||
7
k8s/operator-console/base/console-configmap.yaml
Normal file
7
k8s/operator-console/base/console-configmap.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: console-env
|
||||
data:
|
||||
CONSOLE_PORT: "9090"
|
||||
CONSOLE_TLS_PORT: "9443"
|
||||
30
k8s/operator-console/base/console-deployment.yaml
Normal file
30
k8s/operator-console/base/console-deployment.yaml
Normal file
@@ -0,0 +1,30 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: console
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: console
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: console
|
||||
spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:latest
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_OPERATOR_MODE
|
||||
value: "on"
|
||||
args:
|
||||
- /console
|
||||
- server
|
||||
ports:
|
||||
- containerPort: 9090
|
||||
name: http
|
||||
- containerPort: 9433
|
||||
name: https
|
||||
5
k8s/operator-console/base/console-service-account.yaml
Normal file
5
k8s/operator-console/base/console-service-account.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: console-sa
|
||||
namespace: default
|
||||
14
k8s/operator-console/base/console-service.yaml
Normal file
14
k8s/operator-console/base/console-service.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: console
|
||||
labels:
|
||||
name: console
|
||||
spec:
|
||||
ports:
|
||||
- port: 9090
|
||||
name: http
|
||||
- port: 9443
|
||||
name: https
|
||||
selector:
|
||||
app: console
|
||||
11
k8s/operator-console/base/kustomization.yaml
Normal file
11
k8s/operator-console/base/kustomization.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
# beginning of customizations
|
||||
resources:
|
||||
- console-service-account.yaml
|
||||
- console-cluster-role.yaml
|
||||
- console-cluster-role-binding.yaml
|
||||
- console-configmap.yaml
|
||||
- console-service.yaml
|
||||
- console-deployment.yaml
|
||||
- minio-operator.yaml
|
||||
282
k8s/operator-console/base/minio-operator.yaml
Normal file
282
k8s/operator-console/base/minio-operator.yaml
Normal file
@@ -0,0 +1,282 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: minio-operator
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: tenants.minio.min.io
|
||||
spec:
|
||||
group: minio.min.io
|
||||
scope: Namespaced
|
||||
names:
|
||||
kind: Tenant
|
||||
singular: tenant
|
||||
plural: tenants
|
||||
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:
|
||||
metadata:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
image:
|
||||
type: string
|
||||
serviceName:
|
||||
type: string
|
||||
serviceAccountName:
|
||||
type: string
|
||||
zones:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
servers:
|
||||
type: integer
|
||||
volumesPerServer:
|
||||
type: integer
|
||||
volumeClaimTemplate:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
resources:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
nodeSelector:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
affinity:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
tolerations:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
mountPath:
|
||||
type: string
|
||||
podManagementPolicy:
|
||||
type: string
|
||||
enum: [Parallel,OrderedReady]
|
||||
default: Parallel
|
||||
requestAutoCert:
|
||||
type: boolean
|
||||
default: false
|
||||
certConfig:
|
||||
type: object
|
||||
properties:
|
||||
commonName:
|
||||
type: string
|
||||
organizationName:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
dnsNames:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
version:
|
||||
type: string
|
||||
mountpath:
|
||||
type: string
|
||||
subpath:
|
||||
type: string
|
||||
nodeSelector:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
credsSecret:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
env:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
console:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
properties:
|
||||
metadata:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
image:
|
||||
type: string
|
||||
replicas:
|
||||
type: integer
|
||||
default: 2
|
||||
consoleSecret:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
resources:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
env:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
kes:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
properties:
|
||||
metadata:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
image:
|
||||
type: string
|
||||
replicas:
|
||||
type: integer
|
||||
default: 2
|
||||
kesSecret:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
liveness:
|
||||
type: object
|
||||
properties:
|
||||
initialDelaySeconds:
|
||||
type: integer
|
||||
periodSeconds:
|
||||
type: integer
|
||||
timeoutSeconds:
|
||||
type: integer
|
||||
status:
|
||||
type: object
|
||||
properties:
|
||||
currentState:
|
||||
type: string
|
||||
subresources:
|
||||
# status enables the status subresource.
|
||||
status: {}
|
||||
additionalPrinterColumns:
|
||||
- name: Current State
|
||||
type: string
|
||||
jsonPath: ".status.currentState"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: minio-operator
|
||||
namespace: default
|
||||
---
|
||||
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:
|
||||
- certificates.k8s.io
|
||||
resourceNames:
|
||||
- kubernetes.io/legacy-unknown
|
||||
resources:
|
||||
- signers
|
||||
verbs:
|
||||
- approve
|
||||
- sign
|
||||
- apiGroups:
|
||||
- minio.min.io
|
||||
resources:
|
||||
- '*'
|
||||
verbs:
|
||||
- '*'
|
||||
- apiGroups:
|
||||
- min.io
|
||||
resources:
|
||||
- '*'
|
||||
verbs:
|
||||
- '*'
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
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:
|
||||
containers:
|
||||
- image: minio/k8s-operator:v3.0.1
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: minio-operator
|
||||
serviceAccountName: minio-operator
|
||||
20
k8s/tools.go
Normal file
20
k8s/tools.go
Normal 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
35
k8s/update-codegen.sh
Executable 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/console/pkg/generated \
|
||||
github.com/minio/console/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
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
98
models/bulk_user_groups.go
Normal file
98
models/bulk_user_groups.go
Normal 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
|
||||
}
|
||||
162
models/create_tenant_request.go
Normal file
162
models/create_tenant_request.go
Normal file
@@ -0,0 +1,162 @@
|
||||
// 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 console
|
||||
EnableConsole *bool `json:"enable_console,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"`
|
||||
|
||||
// zones
|
||||
// Required: true
|
||||
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.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) validateZones(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("zones", "body", m.Zones); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
63
models/create_tenant_response.go
Normal file
63
models/create_tenant_response.go
Normal 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
|
||||
}
|
||||
100
models/list_tenants_response.go
Normal file
100
models/list_tenants_response.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
98
models/login_oauth2_auth_request.go
Normal file
98
models/login_oauth2_auth_request.go
Normal 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
|
||||
}
|
||||
81
models/login_operator_request.go
Normal file
81
models/login_operator_request.go
Normal 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
|
||||
}
|
||||
104
models/nofitication_service.go
Normal file
104
models/nofitication_service.go
Normal 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
|
||||
}
|
||||
97
models/notif_endpoint_response.go
Normal file
97
models/notif_endpoint_response.go
Normal 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
|
||||
}
|
||||
129
models/notification_delete_request.go
Normal file
129
models/notification_delete_request.go
Normal 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
|
||||
}
|
||||
114
models/notification_endpoint.go
Normal file
114
models/notification_endpoint.go
Normal 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
|
||||
}
|
||||
92
models/notification_endpoint_item.go
Normal file
92
models/notification_endpoint_item.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
100
models/resource_quota.go
Normal 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
|
||||
}
|
||||
66
models/resource_quota_element.go
Normal file
66
models/resource_quota_element.go
Normal 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
|
||||
}
|
||||
63
models/service_account_creds.go
Normal file
63
models/service_account_creds.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
37
models/service_accounts.go
Normal file
37
models/service_accounts.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
118
models/tenant.go
Normal file
118
models/tenant.go
Normal file
@@ -0,0 +1,118 @@
|
||||
// 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"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// 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
81
models/tenant_list.go
Normal 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
|
||||
}
|
||||
85
models/update_tenant_request.go
Normal file
85
models/update_tenant_request.go
Normal 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
98
models/update_user.go
Normal 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
|
||||
}
|
||||
81
models/update_user_groups.go
Normal file
81
models/update_user_groups.go
Normal 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
|
||||
}
|
||||
181
models/zone.go
Normal file
181
models/zone.go
Normal file
@@ -0,0 +1,181 @@
|
||||
// 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
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// servers
|
||||
// Required: true
|
||||
Servers *int64 `json:"servers"`
|
||||
|
||||
// volume configuration
|
||||
// Required: true
|
||||
VolumeConfiguration *ZoneVolumeConfiguration `json:"volume_configuration"`
|
||||
|
||||
// volumes per server
|
||||
// Required: true
|
||||
VolumesPerServer *int32 `json:"volumes_per_server"`
|
||||
}
|
||||
|
||||
// Validate validates this zone
|
||||
func (m *Zone) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateServers(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateVolumeConfiguration(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateVolumesPerServer(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Zone) validateServers(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("servers", "body", m.Servers); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Zone) 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 *Zone) validateVolumesPerServer(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.Required("volumes_per_server", "body", m.VolumesPerServer); 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
|
||||
}
|
||||
|
||||
// ZoneVolumeConfiguration zone volume configuration
|
||||
//
|
||||
// swagger:model ZoneVolumeConfiguration
|
||||
type ZoneVolumeConfiguration struct {
|
||||
|
||||
// size
|
||||
// Required: true
|
||||
Size *int64 `json:"size"`
|
||||
|
||||
// storage class name
|
||||
StorageClassName string `json:"storage_class_name,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this zone volume configuration
|
||||
func (m *ZoneVolumeConfiguration) 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 *ZoneVolumeConfiguration) 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 *ZoneVolumeConfiguration) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *ZoneVolumeConfiguration) UnmarshalBinary(b []byte) error {
|
||||
var res ZoneVolumeConfiguration
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -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 Console Operator mode status set on env variable or default one
|
||||
func GetOperatorMode() bool {
|
||||
return strings.ToLower(env.Get(consoleOperatorMode, "off")) == "on"
|
||||
}
|
||||
21
pkg/acl/const.go
Normal file
21
pkg/acl/const.go
Normal 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 (
|
||||
consoleOperatorMode = "CONSOLE_OPERATOR_MODE"
|
||||
)
|
||||
315
pkg/acl/endpoints.go
Normal file
315
pkg/acl/endpoints.go
Normal 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
190
pkg/acl/endpoints_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
21
pkg/apis/networking.gke.io/v1beta1/doc.go
Normal file
21
pkg/apis/networking.gke.io/v1beta1/doc.go
Normal 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
|
||||
56
pkg/apis/networking.gke.io/v1beta1/register.go
Normal file
56
pkg/apis/networking.gke.io/v1beta1/register.go
Normal 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
|
||||
}
|
||||
87
pkg/apis/networking.gke.io/v1beta1/types.go
Normal file
87
pkg/apis/networking.gke.io/v1beta1/types.go
Normal 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"`
|
||||
}
|
||||
144
pkg/apis/networking.gke.io/v1beta1/zz_generated.deepcopy.go
Normal file
144
pkg/apis/networking.gke.io/v1beta1/zz_generated.deepcopy.go
Normal 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
|
||||
}
|
||||
21
pkg/apis/networking.gke.io/v1beta2/doc.go
Normal file
21
pkg/apis/networking.gke.io/v1beta2/doc.go
Normal 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
|
||||
56
pkg/apis/networking.gke.io/v1beta2/register.go
Normal file
56
pkg/apis/networking.gke.io/v1beta2/register.go
Normal 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
|
||||
}
|
||||
87
pkg/apis/networking.gke.io/v1beta2/types.go
Normal file
87
pkg/apis/networking.gke.io/v1beta2/types.go
Normal 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"`
|
||||
}
|
||||
144
pkg/apis/networking.gke.io/v1beta2/zz_generated.deepcopy.go
Normal file
144
pkg/apis/networking.gke.io/v1beta2/zz_generated.deepcopy.go
Normal 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
49
pkg/auth/idp.go
Normal 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/console/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()
|
||||
}
|
||||
71
pkg/auth/idp/oauth2/config.go
Normal file
71
pkg/auth/idp/oauth2/config.go
Normal 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/console/pkg/auth/utils"
|
||||
"github.com/minio/minio/pkg/env"
|
||||
)
|
||||
|
||||
func GetIdpURL() string {
|
||||
return env.Get(ConsoleIdpURL, "")
|
||||
}
|
||||
|
||||
func GetIdpClientID() string {
|
||||
return env.Get(ConsoleIdpClientID, "")
|
||||
}
|
||||
|
||||
func GetIdpSecret() string {
|
||||
return env.Get(ConsoleIdpSecret, "")
|
||||
}
|
||||
|
||||
// Public endpoint used by the identity oidcProvider when redirecting the user after identity verification
|
||||
func GetIdpCallbackURL() string {
|
||||
return env.Get(ConsoleIdpCallbackURL, "")
|
||||
}
|
||||
|
||||
func GetIdpAdminRoles() string {
|
||||
return env.Get(ConsoleIdpAdminRoles, "")
|
||||
}
|
||||
|
||||
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(ConsoleIdpHmacPassphrase, 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(ConsoleIdpHmacSalt, defaultSaltForIdpHmac)
|
||||
}
|
||||
|
||||
// GetSaltForIdpHmac returns the policy to be assigned to the users authenticating via an IDP
|
||||
func GetIDPPolicyForUser() string {
|
||||
return env.Get(ConsoleIdpPolicyUser, "consoleAdmin")
|
||||
}
|
||||
29
pkg/auth/idp/oauth2/const.go
Normal file
29
pkg/auth/idp/oauth2/const.go
Normal 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
|
||||
ConsoleIdpURL = "CONSOLE_IDP_URL"
|
||||
ConsoleIdpClientID = "CONSOLE_IDP_CLIENT_ID"
|
||||
ConsoleIdpSecret = "CONSOLE_IDP_SECRET"
|
||||
ConsoleIdpCallbackURL = "CONSOLE_IDP_CALLBACK"
|
||||
ConsoleIdpAdminRoles = "CONSOLE_IDP_ADMIN_ROLES"
|
||||
ConsoleIdpHmacPassphrase = "CONSOLE_IDP_HMAC_PASSPHRASE"
|
||||
ConsoleIdpHmacSalt = "CONSOLE_IDP_HMAC_SALT"
|
||||
ConsoleIdpPolicyUser = "CONSOLE_IDP_POLICY_USER"
|
||||
)
|
||||
229
pkg/auth/idp/oauth2/provider.go
Normal file
229
pkg/auth/idp/oauth2/provider.go
Normal 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/console/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 CONSOLE_IDP_HMAC_PASSPHRASE with CONSOLE_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 Console, 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)
|
||||
}
|
||||
98
pkg/auth/idp/oauth2/provider_test.go
Normal file
98
pkg/auth/idp/oauth2/provider_test.go
Normal 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
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user