Skip to content

Commit 9fcd970

Browse files
committed
Add MinioStsSetup createbucket policy.
1 parent 0fb76b1 commit 9fcd970

File tree

4 files changed

+153
-2
lines changed

4 files changed

+153
-2
lines changed

admin-cli/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@
9191
<dependency>
9292
<groupId>org.testcontainers</groupId>
9393
<artifactId>testcontainers</artifactId>
94+
<scope>test</scope>
95+
</dependency>
96+
<dependency>
97+
<groupId>io.minio</groupId>
98+
<artifactId>minio-admin</artifactId>
99+
<version>8.5.17</version>
94100
</dependency>
95101
</dependencies>
96102

admin-cli/src/main/java/cloud/katta/cli/KattaSetupCli.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,23 @@
77
import cloud.katta.cli.commands.hub.StorageProfileArchive;
88
import cloud.katta.cli.commands.login.AuthorizationCode;
99
import cloud.katta.cli.commands.setup.AwsStsSetup;
10+
import cloud.katta.cli.commands.setup.MinioStsSetup;
1011
import cloud.katta.cli.commands.setup.StorageProfileAwsStaticSetup;
1112
import cloud.katta.cli.commands.setup.StorageProfileAwsStsSetup;
1213
import picocli.CommandLine;
1314

1415
@CommandLine.Command(name = "katta-admin-cli",
1516
mixinStandardHelpOptions = true,
1617
subcommands = {
17-
AwsStsSetup.class, CommandLine.HelpCommand.class, StorageProfileAwsStsSetup.class, StorageProfileAwsStaticSetup.class,
18+
// storage
19+
AwsStsSetup.class,
20+
MinioStsSetup.class,
21+
// hub
22+
StorageProfileAwsStsSetup.class, StorageProfileAwsStaticSetup.class,
23+
StorageProfileArchive.class,
24+
// misc.
1825
AuthorizationCode.class,
19-
StorageProfileArchive.class
26+
CommandLine.HelpCommand.class,
2027
})
2128
public class KattaSetupCli {
2229

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) 2025 shift7 GmbH. All rights reserved.
3+
*/
4+
5+
package cloud.katta.cli.commands.setup;
6+
7+
import org.apache.commons.io.IOUtils;
8+
import org.json.JSONArray;
9+
import org.json.JSONObject;
10+
11+
import java.nio.charset.Charset;
12+
import java.util.List;
13+
import java.util.Objects;
14+
import java.util.concurrent.Callable;
15+
16+
import cloud.katta.cli.KattaSetupCli;
17+
import io.minio.admin.MinioAdminClient;
18+
import picocli.CommandLine;
19+
20+
/**
21+
* Sets up MinIO for Katta in STS mode:
22+
* <ul>
23+
* <li>creates/updates OIDC provider for cryptomator, cryptomatorhub and cryptomatorvaults clients.</li>
24+
* <li>creates roles and role policy for
25+
* <ul>
26+
* <li>creating vaults: access restricted to creating buckets with given prefix</li>
27+
* <li>accessing vaults: access restricted to reading/writing to single bucket.</li>
28+
* </ul>
29+
* </li>
30+
* </ul>
31+
* <p>
32+
* See also: <a href="https://github.com/shift7-ch/katta-docs/blob/main/SETUP_KATTA_SERVER.md#setup-aws">Katta Docs</a>.
33+
*/
34+
@CommandLine.Command(name = "minioSetup", description = "Setup/update OIDC provider and roles for STS in MinIO.", mixinStandardHelpOptions = true)
35+
public class MinioStsSetup implements Callable<Void> {
36+
@CommandLine.Option(names = {"--endpointUrl"}, description = "MinIO URL. Example: \"http://localhost:9000\"", required = true)
37+
String endpointUrl;
38+
39+
@CommandLine.Option(names = {"--profileName"}, description = "AWS profile to load AWS credentials from. See ~/.aws/credentials.", required = false)
40+
String profileName;
41+
42+
@CommandLine.Option(names = {"--accessKey"}, description = "Access Key for administering MinIO if no profile is used.", required = false)
43+
String accessKey;
44+
45+
@CommandLine.Option(names = {"--secretKey"}, description = "Secret Key for administering MinIO if no profile is used.", required = false)
46+
String secretKey;
47+
48+
@CommandLine.Option(names = {"--bucketPrefix"}, description = "Bucket Prefix for STS vaults.", required = false, defaultValue = "katta")
49+
String bucketPrefix;
50+
51+
@CommandLine.Option(names = {"--maxSessionDuration"}, description = "Bucket Prefix for STS vaults.", required = false)
52+
Integer maxSessionDuration;
53+
54+
@Override
55+
public Void call() throws Exception {
56+
final String createbucketPolicyName = "cipherduckcreatebucket";
57+
58+
final JSONObject miniocreatebucketpolicy = new JSONObject(IOUtils.toString(KattaSetupCli.class.getResourceAsStream("/setup/minio_sts/createbucketpolicy.json"), Charset.defaultCharset()));
59+
final MinioAdminClient minioAdminClient = new MinioAdminClient.Builder()
60+
.credentials(accessKey, secretKey)
61+
.endpoint(endpointUrl).build();
62+
63+
// /mc admin policy create myminio cipherduckcreatebucket /setup/minio_sts/createbucketpolicy.json
64+
final JSONArray statements = miniocreatebucketpolicy.getJSONArray("Statement");
65+
for(int i = 0; i < statements.length(); i++) {
66+
final List<String> list = statements.getJSONObject(i).getJSONArray("Resource").toList().stream().map(Objects::toString).map(s -> s.replace("katta", bucketPrefix)).toList();
67+
statements.getJSONObject(i).put("Resource", list);
68+
}
69+
minioAdminClient.addCannedPolicy(createbucketPolicyName, miniocreatebucketpolicy.toString());
70+
System.out.println(minioAdminClient.listCannedPolicies().get(createbucketPolicyName));
71+
72+
73+
// /mc admin policy create myminio cipherduckaccessbucket /setup/minio_sts/accessbucketpolicy.json
74+
//
75+
//
76+
// /mc idp openid add myminio cryptomator \
77+
// config_url="${HUB_KEYCLOAK_URL}${HUB_KEYCLOAK_BASEPATH}/realms/${HUB_KEYCLOAK_REALM}/.well-known/openid-configuration" \
78+
// client_id="cryptomator" \
79+
// client_secret="ignore-me" \
80+
// role_policy="cipherduckcreatebucket"
81+
// /mc idp openid add myminio cryptomatorhub \
82+
// config_url="${HUB_KEYCLOAK_URL}${HUB_KEYCLOAK_BASEPATH}/realms/${HUB_KEYCLOAK_REALM}/.well-known/openid-configuration" \
83+
// client_id="cryptomatorhub" \
84+
// client_secret="ignore-me" \
85+
// role_policy="cipherduckcreatebucket"
86+
// /mc idp openid add myminio cryptomatorvaults \
87+
// config_url="${HUB_KEYCLOAK_URL}${HUB_KEYCLOAK_BASEPATH}/realms/${HUB_KEYCLOAK_REALM}/.well-known/openid-configuration" \
88+
// client_id="cryptomatorvaults" \
89+
// client_secret="ignore-me" \
90+
// role_policy="cipherduckaccessbucket"
91+
92+
return null;
93+
}
94+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2025 shift7 GmbH. All rights reserved.
3+
*/
4+
5+
package cloud.katta.cli.commands.setup;
6+
7+
import org.json.JSONArray;
8+
import org.json.JSONObject;
9+
import org.junit.jupiter.api.Test;
10+
11+
import java.util.Objects;
12+
13+
import cloud.katta.cli.KattaSetupCli;
14+
import cloud.katta.testcontainers.AbtractAdminCliIT;
15+
import io.minio.admin.MinioAdminClient;
16+
import picocli.CommandLine;
17+
18+
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
20+
class MinioStsSetupIT extends AbtractAdminCliIT {
21+
22+
@Test
23+
public void testStorageProfileAwsStsSetup() throws Exception {
24+
int rc = new CommandLine(new KattaSetupCli()).execute(
25+
"minioSetup",
26+
"--endpointUrl", "http://localhost:9100",
27+
"--accessKey", "minioadmin",
28+
"--secretKey", "minioadmin",
29+
"--bucketPrefix", "farfalle"
30+
);
31+
assertEquals(0, rc);
32+
33+
final MinioAdminClient minioAdminClient = new MinioAdminClient.Builder()
34+
.credentials("minioadmin", "minioadmin")
35+
.endpoint("http://localhost:9100").build();
36+
final JSONObject miniocreatebucketpolicy = new JSONObject(minioAdminClient.listCannedPolicies().get("cipherduckcreatebucket"));
37+
final JSONArray statements = miniocreatebucketpolicy.getJSONArray("Statement");
38+
int count = 0;
39+
for(int i = 0; i < statements.length(); i++) {
40+
count += statements.getJSONObject(i).getJSONArray("Resource").toList().stream().map(Objects::toString).map(s -> s.contains("farfalle")).count();
41+
}
42+
assertEquals(3, count);
43+
}
44+
}

0 commit comments

Comments
 (0)