0%

在 MinIO 中使用基于 STS AssumeRole 获取临时访问授权的示例

MinIO 是啥

摘一个官网的简介:

MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。

MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。

更多的介绍、配置等内容移步MinIO Quickstart Guide

本文主要学习记录了如何在 MinIO 中使用基于 AssumeRole 的 STS 方式来获取临时访问授权的步骤。

STS 临时授权(STS temporary credentials)可以为第三方应用、自有应用或应用内不同用户(即用户由自有平台管理)颁发一个自定义时效和权限的访问凭证。

MINIO 的 docker 安装

先参考官方的 quickstart guide 安装 minio docker 容器实例:

1
2
3
4
docker run -p 19000:9000 \
-e "MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE" \
-e "MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
minio/minio server /data

下面为执行输出的前台日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Unable to find image 'minio/minio:latest' locally
latest: Pulling from minio/minio
4753a4528f5f: Pull complete
c0194df27eff: Pull complete
c983f2adaab3: Pull complete
41cdb28672c3: Pull complete
68d7f40ab5fc: Pull complete
61a2f0d36d18: Pull complete
8ddabc7744c0: Pull complete
Digest: sha256:4d031ecabbca313c13d44588b82ef94186e976c98fc15d8eb6bb2d4082be944c
Status: Downloaded newer image for minio/minio:latest
Attempting encryption of all config, IAM users and policies on MinIO backend
Endpoint: http://172.17.0.2:9000 http://127.0.0.1:9000

Browser Access:
http://172.17.0.2:9000 http://127.0.0.1:9000

Object API (Amazon S3 compatible):
Go: https://docs.min.io/docs/golang-client-quickstart-guide
Java: https://docs.min.io/docs/java-client-quickstart-guide
Python: https://docs.min.io/docs/python-client-quickstart-guide
JavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide
.NET: https://docs.min.io/docs/dotnet-client-quickstart-guide

MinIO Client

MinIO Client(mc)提供了很多类 Unix 命令 ls, cat, cp, mirror 等等的工具,并且支持文件系统和 Amazon S3 兼容的云存储服务(AWS Signature V2 和 V4)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
[health@kyc-dev bin]$ ./mc
mc: Configuration written to `/home/health/.mc/config.json`. Please update your access credentials.
mc: Successfully created `/home/health/.mc/share`.
mc: Initialized share uploads `/home/health/.mc/share/uploads.json` file.
mc: Initialized share downloads `/home/health/.mc/share/downloads.json` file.
NAME:
mc - MinIO Client for cloud storage and filesystems.

USAGE:
mc [FLAGS] COMMAND [COMMAND FLAGS | -h] [ARGUMENTS...]

COMMANDS:
alias set, remove and list aliases in configuration file
ls list buckets and objects
mb make a bucket
rb remove a bucket
cp copy objects
mirror synchronize object(s) to a remote site
cat display object contents
head display first 'n' lines of an object
pipe stream STDIN to an object
share generate URL for temporary access to an object
find search for objects
sql run sql queries on objects
stat show object metadata
mv move objects
tree list buckets and objects in a tree format
du summarize disk usage recursively
retention set retention for object(s)
legalhold manage legal hold for object(s)
diff list differences in object name, size, and date between two buckets
rm remove objects
version manage bucket versioning
ilm manage bucket lifecycle
encrypt manage bucket encryption config
event manage object notifications
watch listen for object notification events
undo undo PUT/DELETE operations
policy manage anonymous access to buckets and objects
tag manage tags for bucket and object(s)
replicate configure server side bucket replication
admin manage MinIO servers
update update mc to latest release

GLOBAL FLAGS:
--autocompletion install auto-completion for your shell
--config-dir value, -C value path to configuration folder (default: "/home/health/.mc")
--quiet, -q disable progress bar display
--no-color disable color theme
--json enable JSON lines formatted output
--debug enable debug output
--insecure disable SSL certificate verification
--help, -h show help
--version, -v print the version

TIP:
Use 'mc --autocompletion' to enable shell autocompletion

VERSION:
RELEASE.2021-01-05T05-03-58Z

通过 mc 命令的输出,可以看到 mc 支持丰富的命令和选项。

配置 MC

先配置好 ~/.mc/config.json,如下的 local 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"version": "10",
"aliases": {
"gcs": {
"url": "https://storage.googleapis.com",
"accessKey": "YOUR-ACCESS-KEY-HERE",
"secretKey": "YOUR-SECRET-KEY-HERE",
"api": "S3v2",
"path": "dns"
},
"local": {
"url": "http://192.168.1.77:19000",
"accessKey": "AKIAIOSFODNN7EXAMPLE",
"secretKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"api": "S3v4",
"path": "auto"
},
"play": {
"url": "https://play.min.io",
"accessKey": "Q3AM3UQ867SPQQA43P2F",
"secretKey": "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
"api": "S3v4",
"path": "auto"
},
"s3": {
"url": "https://s3.amazonaws.com",
"accessKey": "YOUR-ACCESS-KEY-HERE",
"secretKey": "YOUR-SECRET-KEY-HERE",
"api": "S3v4",
"path": "dns"
}
}
}

之后,可以通过 mc 的命令来访问和操作 local 服务。

常用命令

更多命令的使用参考命令行帮助或官方的MinIO Client Complete Guide

  • ls,查看 buckets 和 objects;
1
2
3
4
5
6
7
[health@kyc-dev bin]$ ./mc ls -r local
[2020-12-14 12:04:10 CST] 21KiB kyc/images/69f81d9411f5602a4085272e04566de2.jpg
[2021-01-08 10:22:33 CST] 696KiB kyc/videos/2021-01-06_12-03-08.mp4
[health@kyc-dev bin]$
[health@kyc-dev bin]$ ./mc ls -r local/kyc/videos
[2021-01-08 10:22:33 CST] 696KiB 2021-01-06_12-03-08.mp4
[health@kyc-dev bin]$
  • tree,以树状形式列出指定 bucket 或目录下的 objects;
1
2
3
4
5
6
7
[health@kyc-dev bin]$ ./mc tree -f local/kyc
local/kyc
├─ images
│ └─ 69f81d9411f5602a4085272e04566de2.jpg
└─ videos
└─ 2021-01-06_12-03-08.mp4
[health@kyc-dev bin]$
  • stat,查看 bucket 或 object 的 metadata 信息:
1
2
3
4
5
6
7
8
[health@kyc-dev bin]$ ./mc stat local/kyc/videos/2021-01-06_12-03-08.mp4
Name : 2021-01-06_12-03-08.mp4
Date : 2021-01-08 10:22:33 CST
Size : 696 KiB
ETag : bc762953bec48ac74ea57ae2b8abf414
Type : file
Metadata :
Content-Type: video/mp4
  • mb,创建新的 bucket

下面的命令是在 local 服务下创建一个新 bucket: kyc-prj-1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[health@kyc-dev bin]$ ./mc mb --debug local/kyc-prj-1
mc: <DEBUG> PUT /kyc-prj-1/ HTTP/1.1
Host: 192.168.1.77:19000
User-Agent: MinIO (linux; amd64) minio-go/v7.0.7 mc/2021-01-05T05:03:58Z
Content-Length: 0
Authorization: AWS4-HMAC-SHA256 Credential=**REDACTED**/20210108/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=**REDACTED**
X-Amz-Content-Sha256: UNSIGNED-PAYLOAD
X-Amz-Date: 20210108T023512Z
Accept-Encoding: gzip

mc: <DEBUG> HTTP/1.1 200 OK
Content-Length: 0
Accept-Ranges: bytes
Content-Security-Policy: block-all-mixed-content
Date: Fri, 08 Jan 2021 02:35:12 GMT
Location: /kyc-prj-1
Server: MinIO
Vary: Origin
X-Amz-Request-Id: 16582125BE0B83C0
X-Xss-Protection: 1; mode=block

mc: <DEBUG> Response Time: 1.700533ms

Bucket created successfully `local/kyc-prj-1`.
[health@kyc-dev bin]$
  • rb,删除指定的 bucket

下面的命令是删除 local 服务下的 kyc-prj-1 bucket。

1
2
3
4
5
6
[health@kyc-dev bin]$ ./mc rb local/kyc-prj-1
Removed `local/kyc-prj-1` successfully.
[health@kyc-dev bin]$
[health@kyc-dev bin]$ ./mc stat local/kyc-prj-1
mc: <ERROR> Unable to stat `local/kyc-prj-1`. Bucket `kyc-prj-1` does not exist.
[health@kyc-dev bin]$
  • du,递归的查看存储的概览信息

下面的命令已 json 格式递归的输出 local/kyc bucket 下的 objects 的存储占用信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[health@kyc-dev bin]$ ./mc du --json -r local/kyc
{
"prefix": "kyc/images",
"size": 21458,
"status": "success"
}
{
"prefix": "kyc/videos",
"size": 712439,
"status": "success"
}
{
"prefix": "kyc",
"size": 733897,
"status": "success"
}
  • sql,支持在 csv 格式的文件上进行 SQL 查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
[health@kyc-dev bin]$ ./mc sql --help
NAME:
mc sql - run sql queries on objects

USAGE:
mc sql [FLAGS] TARGET [TARGET...]

FLAGS:
--query value, -e value sql query expression (default: "select * from s3object")
--recursive, -r sql query recursively
--csv-input value csv input serialization option
--json-input value json input serialization option
--compression value input compression type
--csv-output value csv output serialization option
--csv-output-header value optional csv output header
--json-output value json output serialization option
--encrypt-key value encrypt/decrypt objects (using server-side encryption with customer provided keys)
--config-dir value, -C value path to configuration folder (default: "/home/health/.mc")
--quiet, -q disable progress bar display
--no-color disable color theme
--json enable JSON lines formatted output
--debug enable debug output
--insecure disable SSL certificate verification
--help, -h show help

ENVIRONMENT VARIABLES:
MC_ENCRYPT_KEY: list of comma delimited prefix=secret values

SERIALIZATION OPTIONS:
For query serialization options, refer to https://docs.min.io/docs/minio-client-complete-guide#sql

EXAMPLES:
1. Run a query on a set of objects recursively on AWS S3.
$ mc sql --recursive --query "select * from S3Object" s3/personalbucket/my-large-csvs/

2. Run a query on an object on MinIO.
$ mc sql --query "select count(s.power) from S3Object" myminio/iot-devices/power-ratio.csv

3. Run a query on an encrypted object with customer provided keys.
$ mc sql --encrypt-key "myminio/iot-devices=32byteslongsecretkeymustbegiven1" \
--query "select count(s.power) from S3Object s" myminio/iot-devices/power-ratio-encrypted.csv

4. Run a query on an object on MinIO in gzip format using ; as field delimiter,
newline as record delimiter and file header to be used
$ mc sql --compression GZIP --csv-input "rd=\n,fh=USE,fd=;" \
--query "select count(s.power) from S3Object" myminio/iot-devices/power-ratio.csv.gz

5. Run a query on an object on MinIO in gzip format using ; as field delimiter,
newline as record delimiter and file header to be used
$ mc sql --compression GZIP --csv-input "rd=\n,fh=USE,fd=;" \
--json-output "rd=\n\n" --query "select * from S3Object" myminio/iot-devices/data.csv

6. Run same query as in 5., but specify csv output headers. If --csv-output-headers is
specified as "", first row of csv is interpreted as header
$ mc sql --compression GZIP --csv-input "rd=\n,fh=USE,fd=;" \
--csv-output "rd=\n" --csv-output-header "device_id,uptime,lat,lon" \
--query "select * from S3Object" myminio/iot-devices/data.csv
[health@kyc-dev bin]$

mc admin 管理员操作命令

可以通过 mc admin 命令来管理用户、策略、配置、监控等管理操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[health@kyc-dev bin]$ mc admin
NAME:
mc admin - manage MinIO servers

USAGE:
mc admin COMMAND [COMMAND FLAGS | -h] [ARGUMENTS...]

COMMANDS:
service restart and stop all MinIO servers
update update all MinIO servers
info display MinIO server information
user manage users
group manage groups
policy manage policies defined in the MinIO server
config manage MinIO server configuration
heal [DEPRECATED] heal disks, buckets and objects on MinIO server
profile generate profile data for debugging purposes
top provide top like statistics for MinIO
trace show http trace for MinIO server
console show console logs for MinIO server
prometheus manages prometheus config
kms perform KMS management operations
subnet Subnet related commands
bucket manage buckets defined in the MinIO server

FLAGS:
--config-dir value, -C value path to configuration folder (default: "/home/health/.mc")
--quiet, -q disable progress bar display
--no-color disable color theme
--json enable JSON lines formatted output
--debug enable debug output
--insecure disable SSL certificate verification
--help, -h show help

[health@kyc-dev bin]$

STS AssumeRole

1. 创建用户

1
2
[health@kyc-dev bin]$ mc admin user add local company-60001 company-60001-123456
Added user `company-60001` successfully.

2. 创建 policy 项目

这里演示创建一个 policy 文件 policy-company-60001.json,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::kyc/60001/*"
]
}
]
}

创建一个 company-60001 的策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[health@kyc-dev bin]$ mc admin policy add local company-60001 ./policy-company.json
Added policy `company-60001` successfully.
[health@kyc-dev bin]$ mc admin policy info local company-60001
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::kyc/60001/*"
]
}
]
}

注:策略文件的 Version 固定设置为 2012-10-17。

为此账号授权 company-60001 的策略

1
2
3
[health@kyc-dev bin]$ mc admin policy set local company-60001 user=company-60001
Policy company-60001 is set on user `company-60001`
[health@kyc-dev bin]$

通过 aws-cli 来获取 AssumeRole STS 授权

  1. 通过 aws configure 来添加配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[health@kyc-dev bin]$ aws configure --profile company-60001
AWS Access Key ID [None]: company-60001
AWS Secret Access Key [None]: company-60001-123456
Default region name [None]: us-east-1
Default output format [None]: json

[health@kyc-dev bin]$ cat ~/.aws/config
[company-60001]
region = us-east-1
output = json

[health@kyc-dev bin]$ cat ~/.aws/credentials
[company-60001]
aws_access_key_id = company-60001
aws_secret_access_key = company-60001-123456
  1. 获取 STS 授权信息的示例命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[health@kyc-dev ~]$ aws --profile newuser \
> --endpoint-url 'http://192.168.1.77:19000' \
> sts assume-role \
> --policy '{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": ["s3:GetObject"],"Resource": ["arn:aws:s3:::*"]}]}' \
> --role-arn 'arn:aws:s3:::kyc/public/*' \
> --role-session-name anything
{
"Credentials": {
"AccessKeyId": "DSS2SDH76C7ITUVNV8MK",
"SecretAccessKey": "J6+MwowTJjVw2VpgFZduX3ZbH+TdcNzuN7dR4+Bk",
"SessionToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJEU1MyU0RINzZDN0lUVVZOVjhNSyIsImV4cCI6MzYwMDAwMDAwMDAwMCwicG9saWN5IjoicmVhZG9ubHkiLCJzZXNzaW9uUG9saWN5IjoiZXlKV1pYSnphVzl1SWpvZ0lqSXdNVEl0TVRBdE1UY2lMQ0pUZEdGMFpXMWxiblFpT2lCYmV5SkZabVpsWTNRaU9pQWlRV3hzYjNjaUxDSkJZM1JwYjI0aU9pQmJJbk16T2tkbGRFOWlhbVZqZENKZExDSlNaWE52ZFhKalpTSTZJRnNpWVhKdU9tRjNjenB6TXpvNk9pb2lYWDFkZlE9PSJ9.fNP2vMvNDX5i7A_N4keuYdKuzaoYjUSAPGTuileROMSrn38Ff8TTzakIq10k4tUtxkHs2kRQhJCUyuoCPJHUyQ",
"Expiration": "2021-01-08T09:29:06+00:00"
},
"AssumedRoleUser": {
"Arn": ""
}
}

MinIO Java SDK 的上传和下载示例

下图贴了一个使用 STS 授权用户访问 MinIO 上的资源的流程:

下面的示例代码是基于 MinIO Java SDK 8.0.3 版本,演示如何基于 AssumeRole STS 的方式来上传下载文件,其他的操作也是类似的。

需要在执行完上面的步骤之后,再来编译执行下面的示例代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public class MinIODemo {

public static final String ENDPOINT = "http://192.168.1.77:19000/";
public static final String ACCESS_KEY_COMPANY = "company-60001";
public static final String SECRET_KEY_COMPANY = "company-60001-123456";
public static final String REGION = "us-east-1";
public static final String BUCKET = "kyc";
public static final String ROLE_ARN = "arn:aws:s3:::kyc/public/*";
public static final String ROLE_SESSION_NAME = "anysession";
public static final String POLICY_GET_AND_PUT = "{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Action\": [\n" +
" \"s3:GetObject\",\n" +
" \"s3:PutObject\"\n" +
" ],\n" +
" \"Resource\": [\n" +
" \"arn:aws:s3:::*\"\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}";

public static void main(String[] args) throws Exception {

// create AssumeRoleProvider instance.
Provider provider = new AssumeRoleProvider(
ENDPOINT,
ACCESS_KEY_COMPANY,
SECRET_KEY_COMPANY,
3600,
POLICY_GET_AND_PUT,
REGION,
ROLE_ARN,
ROLE_SESSION_NAME,
null,
null);

// build new minio client with *AssumeRoleProvider* as credential provider.
MinioClient minioClient = MinioClient.builder()
.endpoint(ENDPOINT)
.credentialsProvider(provider)
.build();

// download object.
String filename = "d4e7fc31b44792387057c6cc37e7ff77.jpg";
GetObjectResponse getObjectResponse = minioClient.getObject(GetObjectArgs.builder()
.bucket(BUCKET).region(REGION)
.object("60001/" + filename)
.build());
byte [] buffer = new byte[getObjectResponse.available()];
getObjectResponse.read(buffer);
Files.write(buffer, new File("/temp/" + filename));
System.out.println("download <" + filename + "> success");

// upload object.
final String uploadFileName = "1609a210-0146-11ea-a430-d7179cc52058.jpg";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("/temp/" + uploadFileName));
minioClient.putObject(PutObjectArgs.builder()
.bucket(BUCKET).region(REGION)
.object("60001/" + uploadFileName)
.stream(bis, bis.available(), -1)
.contentType("image/jpeg")
.build());
System.out.println("upload <" + uploadFileName + "> success");
}
}
  • 这里获取 credential 时传入的 Policy 是我们在上面为 company-60001 创建的策略的子集,本次调用只申请了 GetObject 和 PutObject Action 权限,而没有 DeleteObject Action 权限;
  • 上传文件的示例将本地的图片上传到 kyc bucket 的 60001/ 目录下,如下图:

点击可以查看官方更多的 MinIO Java SDK 的示例代码

Welcome to my other publishing channels