mirror of
https://github.com/minio/minio.git
synced 2025-11-09 13:39:46 -05:00
Add support for Access Management Plugin (#14875)
- This change renames the OPA integration as Access Management Plugin - there is nothing specific to OPA in the integration, it is just a webhook. - OPA configuration is automatically migrated to Access Management Plugin and OPA specific configuration is marked as deprecated. - OPA doc is updated and moved.
This commit is contained in:
committed by
GitHub
parent
edf364bf21
commit
83071a3459
159
docs/iam/access-management-plugin.md
Normal file
159
docs/iam/access-management-plugin.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# Access Management Plugin Guide [](https://slack.minio.io)
|
||||
|
||||
MinIO now includes support for using an Access Management Plugin. This is to allow object storage access control to be managed externally via a webhook.
|
||||
|
||||
When configured, MinIO sends request and credential details for every API call to an external HTTP(S) endpoint and expects an allow/deny response. MinIO is thus able to delegate access management to an external system, and users are able to use a custom solution instead of S3 standard IAM policies.
|
||||
|
||||
Latency sensitive applications may notice an increased latency due to a request to the external plugin upon every authenticated request to MinIO. User are advised to provision their infrastructure such that latency and performance is acceptable.
|
||||
|
||||
## Quickstart
|
||||
|
||||
To easily try out the feature, run the included demo Access Management Plugin program in this directory:
|
||||
|
||||
```sh
|
||||
go run access-manager-plugin.go
|
||||
```
|
||||
|
||||
This program, lets the admin user perform any action and prevents all other users from performing `s3:Put*` operations.
|
||||
|
||||
In another terminal start MinIO:
|
||||
|
||||
```sh
|
||||
export MINIO_CI_CD=1
|
||||
export MINIO_ROOT_USER=minio
|
||||
export MINIO_ROOT_PASSWORD=minio123
|
||||
export MINIO_POLICY_OPA_URL=http://localhost:8080/
|
||||
minio server /tmp/disk{1...4}
|
||||
```
|
||||
|
||||
Now, let's test it out with `mc`:
|
||||
|
||||
```sh
|
||||
mc alias set myminio http://localhost:9000 minio minio123
|
||||
mc ls myminio
|
||||
mc mb myminio/test
|
||||
mc cp /etc/issue myminio/test
|
||||
mc admin user add myminio foo foobar123
|
||||
export MC_HOST_foo=http://foo:foobar123@localhost:9000
|
||||
mc ls foo
|
||||
mc cp /etc/issue myminio/test/issue2
|
||||
```
|
||||
|
||||
Only the last operation would fail with a permissions error.
|
||||
|
||||
## Configuration
|
||||
|
||||
Access Management Plugin can be configured with environment variables:
|
||||
|
||||
```sh
|
||||
$ mc admin config set dminio1 policy_plugin --env
|
||||
KEY:
|
||||
policy_plugin enable Access Management Plugin for policy enforcement
|
||||
|
||||
ARGS:
|
||||
MINIO_POLICY_PLUGIN_URL* (url) plugin hook endpoint (HTTP(S)) e.g. "http://localhost:8181/v1/data/httpapi/authz/allow"
|
||||
MINIO_POLICY_PLUGIN_AUTH_TOKEN (string) authorization token for plugin hook endpoint
|
||||
MINIO_POLICY_PLUGIN_COMMENT (sentence) optionally add a comment to this setting
|
||||
```
|
||||
|
||||
## Request and Response
|
||||
|
||||
MinIO will make a `POST` request with a JSON body to the given plugin URL. If the auth token parameter is set, it will be sent as an authorization header.
|
||||
|
||||
The JSON body structure can be seen from this sample:
|
||||
|
||||
<details><summary>Request Body Sample</summary>
|
||||
|
||||
```json
|
||||
{
|
||||
"input": {
|
||||
"account": "minio",
|
||||
"groups": null,
|
||||
"action": "s3:ListBucket",
|
||||
"bucket": "test",
|
||||
"conditions": {
|
||||
"Authorization": [
|
||||
"AWS4-HMAC-SHA256 Credential=minio/20220507/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=62012db6c47d697620cf6c68f0f45f6e34894589a53ab1faf6dc94338468c78a"
|
||||
],
|
||||
"CurrentTime": [
|
||||
"2022-05-07T18:31:41Z"
|
||||
],
|
||||
"Delimiter": [
|
||||
"/"
|
||||
],
|
||||
"EpochTime": [
|
||||
"1651948301"
|
||||
],
|
||||
"Prefix": [
|
||||
""
|
||||
],
|
||||
"Referer": [
|
||||
""
|
||||
],
|
||||
"SecureTransport": [
|
||||
"false"
|
||||
],
|
||||
"SourceIp": [
|
||||
"127.0.0.1"
|
||||
],
|
||||
"User-Agent": [
|
||||
"MinIO (linux; amd64) minio-go/v7.0.24 mc/DEVELOPMENT.2022-04-20T23-07-53Z"
|
||||
],
|
||||
"UserAgent": [
|
||||
"MinIO (linux; amd64) minio-go/v7.0.24 mc/DEVELOPMENT.2022-04-20T23-07-53Z"
|
||||
],
|
||||
"X-Amz-Content-Sha256": [
|
||||
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
],
|
||||
"X-Amz-Date": [
|
||||
"20220507T183141Z"
|
||||
],
|
||||
"authType": [
|
||||
"REST-HEADER"
|
||||
],
|
||||
"principaltype": [
|
||||
"Account"
|
||||
],
|
||||
"signatureversion": [
|
||||
"AWS4-HMAC-SHA256"
|
||||
],
|
||||
"userid": [
|
||||
"minio"
|
||||
],
|
||||
"username": [
|
||||
"minio"
|
||||
],
|
||||
"versionid": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"owner": true,
|
||||
"object": "",
|
||||
"claims": {},
|
||||
"denyOnly": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
The response expected by MinIO, is a JSON body with a boolean:
|
||||
|
||||
```json
|
||||
{
|
||||
"result": true
|
||||
}
|
||||
```
|
||||
|
||||
The following structure is also accepted:
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"allow": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Any unmentioned JSON object keys in the above are ignored.
|
||||
|
||||
83
docs/iam/access-manager-plugin.go
Normal file
83
docs/iam/access-manager-plugin.go
Normal file
@@ -0,0 +1,83 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
// Copyright (c) 2015-2022 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func writeErrorResponse(w http.ResponseWriter, err error) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"error": fmt.Sprintf("%v", err),
|
||||
})
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Result bool `json:"result"`
|
||||
}
|
||||
|
||||
func mainHandler(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
writeErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
reqMap := make(map[string]interface{})
|
||||
err = json.Unmarshal(body, &reqMap)
|
||||
if err != nil {
|
||||
writeErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// fmt.Printf("request: %#v\n", reqMap)
|
||||
|
||||
m := reqMap["input"].(map[string]interface{})
|
||||
accountValue := m["account"].(string)
|
||||
actionValue := m["action"].(string)
|
||||
|
||||
// Allow user `minio` to perform any action.
|
||||
var res Result
|
||||
if accountValue == "minio" {
|
||||
res.Result = true
|
||||
} else {
|
||||
// All other users may not perform any `s3:Put*` operations.
|
||||
res.Result = true
|
||||
if strings.HasPrefix(actionValue, "s3:Put") {
|
||||
res.Result = false
|
||||
}
|
||||
}
|
||||
fmt.Printf("account: %v | action: %v | allowed: %v\n", accountValue, actionValue, res.Result)
|
||||
json.NewEncoder(w).Encode(res)
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", mainHandler)
|
||||
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
# OPA Quickstart Guide [](https://slack.minio.io)
|
||||
OPA is a lightweight general-purpose policy engine that can be co-located with MinIO server, in this document we talk about how to use OPA HTTP API to authorize requests. It can be used with any type of credentials (STS based like OpenID or LDAP, regular IAM users or service accounts).
|
||||
|
||||
OPA is enabled through MinIO's Access Management Plugin feature.
|
||||
|
||||
## Get started
|
||||
|
||||
### 1. Start OPA in a container
|
||||
@@ -48,10 +50,10 @@ curl -X PUT --data-binary @example.rego \
|
||||
|
||||
### 4. Setup MinIO with OPA
|
||||
|
||||
Set the `MINIO_POLICY_OPA_URL` as the endpoint that MinIO should send authorization requests to. Then start the server.
|
||||
Set the `MINIO_POLICY_PLUGIN_URL` as the endpoint that MinIO should send authorization requests to. Then start the server.
|
||||
|
||||
```sh
|
||||
export MINIO_POLICY_OPA_URL=http://localhost:8181/v1/data/httpapi/authz/allow
|
||||
export MINIO_POLICY_PLUGIN_URL=http://localhost:8181/v1/data/httpapi/authz/allow
|
||||
export MINIO_CI_CD=1
|
||||
export MINIO_ROOT_USER=minio
|
||||
export MINIO_ROOT_PASSWORD=minio123
|
||||
@@ -77,6 +79,3 @@ mc cat foo/test/issue
|
||||
mc cp /etc/issue myminio/test/issue2
|
||||
```
|
||||
|
||||
## Explore Further
|
||||
- [MinIO STS Quickstart Guide](https://docs.minio.io/docs/minio-sts-quickstart-guide)
|
||||
- [The MinIO documentation website](https://docs.minio.io)
|
||||
Reference in New Issue
Block a user