Skip to content

Commit ffbe962

Browse files
author
Mircea Cosbuc
committed
Store mysql credentials in k8s secret
1 parent d54bbc2 commit ffbe962

File tree

5 files changed

+72
-5
lines changed

5 files changed

+72
-5
lines changed

samples/mysql-schema/k8s/crd.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ spec:
1616
properties:
1717
spec:
1818
type: object
19+
required:
20+
- encoding
1921
properties:
2022
encoding:
21-
type: string
23+
type: string

samples/mysql-schema/src/main/java/com/github/containersolutions/operator/sample/MySQLSchemaOperator.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.fabric8.kubernetes.client.Config;
55
import io.fabric8.kubernetes.client.ConfigBuilder;
66
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
7+
import io.fabric8.kubernetes.client.KubernetesClient;
78
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
910
import org.takes.facets.fork.FkRegex;
@@ -21,8 +22,9 @@ public static void main(String[] args) throws IOException {
2122
log.info("MySQL Schema Operator starting");
2223

2324
Config config = new ConfigBuilder().withNamespace(null).build();
24-
Operator operator = new Operator(new DefaultKubernetesClient(config));
25-
operator.registerControllerForAllNamespaces(new SchemaController());
25+
KubernetesClient client = new DefaultKubernetesClient(config);
26+
Operator operator = new Operator(client);
27+
operator.registerControllerForAllNamespaces(new SchemaController(client));
2628

2729
new FtBasic(
2830
new TkFork(new FkRegex("/health", "ALL GOOD!")), 8080

samples/mysql-schema/src/main/java/com/github/containersolutions/operator/sample/SchemaController.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22

33
import com.github.containersolutions.operator.api.Controller;
44
import com.github.containersolutions.operator.api.ResourceController;
5+
import io.fabric8.kubernetes.api.model.Secret;
6+
import io.fabric8.kubernetes.api.model.SecretBuilder;
7+
import io.fabric8.kubernetes.client.KubernetesClient;
8+
import org.apache.commons.lang.RandomStringUtils;
59
import org.slf4j.Logger;
610
import org.slf4j.LoggerFactory;
711

812
import java.sql.Connection;
913
import java.sql.DriverManager;
1014
import java.sql.ResultSet;
1115
import java.sql.SQLException;
16+
import java.util.Base64;
1217
import java.util.Optional;
1318

1419
import static java.lang.String.format;
@@ -17,10 +22,15 @@
1722
crdName = "schemas.mysql.sample.javaoperatorsdk",
1823
customResourceClass = Schema.class)
1924
public class SchemaController implements ResourceController<Schema> {
20-
25+
static final String USERNAME_FORMAT = "%s-user";
26+
static final String SECRET_FORMAT = "%s-secret";
2127

2228
private final Logger log = LoggerFactory.getLogger(getClass());
2329

30+
private final KubernetesClient kubernetesClient;
31+
32+
public SchemaController(KubernetesClient kubernetesClient) { this.kubernetesClient = kubernetesClient; }
33+
2434
@Override
2535
public Optional<Schema> createOrUpdateResource(Schema schema) {
2636
try (Connection connection = getConnection()) {
@@ -29,14 +39,36 @@ public Optional<Schema> createOrUpdateResource(Schema schema) {
2939
schema.getMetadata().getName(),
3040
schema.getSpec().getEncoding()));
3141

42+
String password = RandomStringUtils.randomAlphanumeric(16);
43+
String userName = String.format(USERNAME_FORMAT,
44+
schema.getMetadata().getName());
45+
String secretName = String.format(SECRET_FORMAT,
46+
schema.getMetadata().getName());
47+
connection.createStatement().execute(format(
48+
"CREATE USER '%1$s' IDENTIFIED BY '%2$s'",
49+
userName, password));
50+
connection.createStatement().execute(format(
51+
"GRANT ALL ON `%1$s`.* TO '%2$s'",
52+
schema.getMetadata().getName(), userName));
53+
Secret credentialsSecret = new SecretBuilder()
54+
.withNewMetadata().withName(secretName).endMetadata()
55+
.addToData("MYSQL_USERNAME", Base64.getEncoder().encodeToString(userName.getBytes()))
56+
.addToData("MYSQL_PASSWORD", Base64.getEncoder().encodeToString(password.getBytes()))
57+
.build();
58+
this.kubernetesClient.secrets()
59+
.inNamespace(schema.getMetadata().getNamespace())
60+
.create(credentialsSecret);
61+
3262
SchemaStatus status = new SchemaStatus();
3363
status.setUrl(format("jdbc:mysql://%1$s/%2$s",
3464
System.getenv("MYSQL_HOST"),
3565
schema.getMetadata().getName()));
66+
status.setUserName(userName);
67+
status.setSecretName(secretName);
3668
status.setStatus("CREATED");
3769
schema.setStatus(status);
38-
3970
log.info("Schema {} created", schema.getMetadata().getName());
71+
4072
return Optional.of(schema);
4173
}
4274
return Optional.empty();
@@ -45,6 +77,8 @@ public Optional<Schema> createOrUpdateResource(Schema schema) {
4577

4678
SchemaStatus status = new SchemaStatus();
4779
status.setUrl(null);
80+
status.setUserName(null);
81+
status.setSecretName(null);
4882
status.setStatus("ERROR");
4983
schema.setStatus(status);
5084

@@ -60,6 +94,16 @@ public boolean deleteResource(Schema schema) {
6094
if (schemaExists(connection, schema.getMetadata().getName())) {
6195
connection.createStatement().execute("DROP DATABASE `" + schema.getMetadata().getName() + "`");
6296
log.info("Deleted Schema '{}'", schema.getMetadata().getName());
97+
98+
if (userExists(connection, schema.getStatus().getUserName())) {
99+
connection.createStatement().execute("DROP USER '" + schema.getStatus().getUserName() + "'");
100+
log.info("Deleted User '{}'", schema.getStatus().getUserName());
101+
}
102+
103+
this.kubernetesClient.secrets()
104+
.inNamespace(schema.getMetadata().getNamespace())
105+
.withName(schema.getStatus().getSecretName())
106+
.delete();
63107
} else {
64108
log.info("Delete event ignored for schema '{}', real schema doesn't exist",
65109
schema.getMetadata().getName());
@@ -86,4 +130,10 @@ private boolean schemaExists(Connection connection, String schemaName) throws SQ
86130
return resultSet.first();
87131
}
88132

133+
private boolean userExists(Connection connection, String userName) throws SQLException {
134+
ResultSet resultSet = connection.createStatement().executeQuery(
135+
format("SELECT User FROM mysql.user WHERE User='%1$s'", userName)
136+
);
137+
return resultSet.first();
138+
}
89139
}

samples/mysql-schema/src/main/java/com/github/containersolutions/operator/sample/SchemaSpec.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ public String getEncoding() {
1111
public void setEncoding(String encoding) {
1212
this.encoding = encoding;
1313
}
14+
1415
}

samples/mysql-schema/src/main/java/com/github/containersolutions/operator/sample/SchemaStatus.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ public class SchemaStatus {
66

77
private String status;
88

9+
private String userName;
10+
11+
private String secretName;
12+
913
public String getUrl() {
1014
return url;
1115
}
@@ -21,4 +25,12 @@ public String getStatus() {
2125
public void setStatus(String status) {
2226
this.status = status;
2327
}
28+
29+
public String getUserName() { return userName; }
30+
31+
public void setUserName(String userName) { this.userName = userName; }
32+
33+
public String getSecretName() { return secretName; }
34+
35+
public void setSecretName(String secretName) { this.secretName = secretName; }
2436
}

0 commit comments

Comments
 (0)