Skip to content

Commit 5091283

Browse files
committed
feat: allow to encrypt stored object with libsodium or OpenPGP
1 parent ce5c3e3 commit 5091283

21 files changed

Lines changed: 938 additions & 90 deletions

File tree

stackgres-k8s/e2e/spec/backup.values.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ configurations:
44
shared_buffers: '32MB'
55
objectstorage:
66
create: true
7+
encryption:
8+
method: sodium
9+
sodium:
10+
key:
11+
name: backup-minio
12+
key: secretkey
713
cluster:
814
pods:
915
persistentVolume:

stackgres-k8s/e2e/utils/cluster

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/sh
22

33
export E2E_DISABLE_RESOURCE_REQUIREMENTS="${E2E_DISABLE_RESOURCE_REQUIREMENTS:-true}"
4-
export E2E_POSTGRES_VERSION="${E2E_POSTGRES_VERSION:-16.4}"
4+
export E2E_POSTGRES_VERSION="${E2E_POSTGRES_VERSION:-16.8}"
55
export E2E_POSTGRES_BABELFISH_VERSION="${E2E_POSTGRES_BABELFISH_VERSION:-16.4}"
66

77
create_or_replace_cluster_without_defaults() {

stackgres-k8s/install/helm/stackgres-cluster/templates/sgobjectstorage.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ metadata:
1212
app.kubernetes.io/managed-by: "Helm"
1313
{{- end }}
1414
spec:
15+
{{- with .Values.configurations.objectstorage.encryption }}
16+
encryption:
17+
{{- toYaml . | nindent 4 }}
18+
{{- end }}
1519
{{- if not (or .Values.configurations.objectstorage.s3 .Values.configurations.objectstorage.s3Compatible .Values.configurations.objectstorage.gcs .Values.configurations.objectstorage.azureBlob) }}
1620
type: s3Compatible
1721
s3Compatible:

stackgres-k8s/src/common/src/main/java/io/stackgres/common/crd/storages/BackupStorage.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ public class BackupStorage {
4040
@Valid
4141
private AzureBlobStorage azureBlob;
4242

43+
@Valid
44+
private StorageEncryption encryption;
45+
4346
public String getType() {
4447
return type;
4548
}
@@ -100,9 +103,17 @@ public Optional<AzureBlobStorage> getAzureBlobOpt() {
100103
return Optional.ofNullable(azureBlob);
101104
}
102105

106+
public StorageEncryption getEncryption() {
107+
return encryption;
108+
}
109+
110+
public void setEncryption(StorageEncryption encryption) {
111+
this.encryption = encryption;
112+
}
113+
103114
@Override
104115
public int hashCode() {
105-
return Objects.hash(azureBlob, gcs, s3, s3Compatible, type);
116+
return Objects.hash(azureBlob, encryption, gcs, s3, s3Compatible, type);
106117
}
107118

108119
@Override
@@ -114,7 +125,8 @@ public boolean equals(Object obj) {
114125
return false;
115126
}
116127
BackupStorage other = (BackupStorage) obj;
117-
return Objects.equals(azureBlob, other.azureBlob) && Objects.equals(gcs, other.gcs)
128+
return Objects.equals(azureBlob, other.azureBlob)
129+
&& Objects.equals(encryption, other.encryption) && Objects.equals(gcs, other.gcs)
118130
&& Objects.equals(s3, other.s3) && Objects.equals(s3Compatible, other.s3Compatible)
119131
&& Objects.equals(type, other.type);
120132
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (C) 2019 OnGres, Inc.
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
package io.stackgres.common.crd.storages;
7+
8+
import java.util.Objects;
9+
10+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
11+
import com.fasterxml.jackson.annotation.JsonInclude;
12+
import io.quarkus.runtime.annotations.RegisterForReflection;
13+
import io.stackgres.common.StackGresUtil;
14+
import io.stackgres.common.crd.SecretKeySelector;
15+
import io.sundr.builder.annotations.Buildable;
16+
import jakarta.validation.Valid;
17+
import jakarta.validation.constraints.NotNull;
18+
19+
@RegisterForReflection
20+
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
21+
@JsonIgnoreProperties(ignoreUnknown = true)
22+
@Buildable(editableEnabled = false, validationEnabled = false, generateBuilderPackage = false,
23+
lazyCollectionInitEnabled = false, lazyMapInitEnabled = false,
24+
builderPackage = "io.fabric8.kubernetes.api.builder")
25+
public class OpenPgpStorageEncryption {
26+
27+
@NotNull(message = "The key is required")
28+
@Valid
29+
private SecretKeySelector key;
30+
31+
@Valid
32+
private SecretKeySelector keyPassphrase;
33+
34+
public SecretKeySelector getKey() {
35+
return key;
36+
}
37+
38+
public void setKey(SecretKeySelector key) {
39+
this.key = key;
40+
}
41+
42+
public SecretKeySelector getKeyPassphrase() {
43+
return keyPassphrase;
44+
}
45+
46+
public void setKeyPassphrase(SecretKeySelector keyPassphrase) {
47+
this.keyPassphrase = keyPassphrase;
48+
}
49+
50+
@Override
51+
public int hashCode() {
52+
return Objects.hash(key, keyPassphrase);
53+
}
54+
55+
@Override
56+
public boolean equals(Object obj) {
57+
if (this == obj) {
58+
return true;
59+
}
60+
if (!(obj instanceof OpenPgpStorageEncryption)) {
61+
return false;
62+
}
63+
OpenPgpStorageEncryption other = (OpenPgpStorageEncryption) obj;
64+
return Objects.equals(key, other.key) && Objects.equals(keyPassphrase, other.keyPassphrase);
65+
}
66+
67+
@Override
68+
public String toString() {
69+
return StackGresUtil.toPrettyYaml(this);
70+
}
71+
72+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (C) 2019 OnGres, Inc.
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
package io.stackgres.common.crd.storages;
7+
8+
import org.jetbrains.annotations.NotNull;
9+
10+
public enum SodiumKeyTransformation {
11+
12+
BASE64("base64"),
13+
HEX("hex"),
14+
NONE("none");
15+
16+
private final @NotNull String type;
17+
18+
SodiumKeyTransformation(@NotNull String type) {
19+
this.type = type;
20+
}
21+
22+
@Override
23+
public @NotNull String toString() {
24+
return type;
25+
}
26+
27+
public static @NotNull SodiumKeyTransformation fromString(@NotNull String value) {
28+
for (SodiumKeyTransformation role : SodiumKeyTransformation.values()) {
29+
if (role.toString().equals(value)) {
30+
return role;
31+
}
32+
}
33+
throw new IllegalArgumentException("Unknown sodium key transformation " + value);
34+
}
35+
36+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (C) 2019 OnGres, Inc.
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
package io.stackgres.common.crd.storages;
7+
8+
import java.util.Objects;
9+
10+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
11+
import com.fasterxml.jackson.annotation.JsonInclude;
12+
import io.quarkus.runtime.annotations.RegisterForReflection;
13+
import io.stackgres.common.StackGresUtil;
14+
import io.stackgres.common.crd.SecretKeySelector;
15+
import io.stackgres.common.validation.ValidEnum;
16+
import io.sundr.builder.annotations.Buildable;
17+
import jakarta.validation.Valid;
18+
import jakarta.validation.constraints.NotNull;
19+
20+
@RegisterForReflection
21+
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
22+
@JsonIgnoreProperties(ignoreUnknown = true)
23+
@Buildable(editableEnabled = false, validationEnabled = false, generateBuilderPackage = false,
24+
lazyCollectionInitEnabled = false, lazyMapInitEnabled = false,
25+
builderPackage = "io.fabric8.kubernetes.api.builder")
26+
public class SodiumStorageEncryption {
27+
28+
@NotNull(message = "The key is required")
29+
@Valid
30+
private SecretKeySelector key;
31+
32+
@ValidEnum(enumClass = SodiumKeyTransformation.class, allowNulls = true,
33+
message = "keyTransform can be base64, hex or none")
34+
private String keyTransform;
35+
36+
public SecretKeySelector getKey() {
37+
return key;
38+
}
39+
40+
public void setKey(SecretKeySelector key) {
41+
this.key = key;
42+
}
43+
44+
public String getKeyTransform() {
45+
return keyTransform;
46+
}
47+
48+
public void setKeyTransform(String keyTransform) {
49+
this.keyTransform = keyTransform;
50+
}
51+
52+
@Override
53+
public int hashCode() {
54+
return Objects.hash(key, keyTransform);
55+
}
56+
57+
@Override
58+
public boolean equals(Object obj) {
59+
if (this == obj) {
60+
return true;
61+
}
62+
if (!(obj instanceof SodiumStorageEncryption)) {
63+
return false;
64+
}
65+
SodiumStorageEncryption other = (SodiumStorageEncryption) obj;
66+
return Objects.equals(key, other.key) && Objects.equals(keyTransform, other.keyTransform);
67+
}
68+
69+
@Override
70+
public String toString() {
71+
return StackGresUtil.toPrettyYaml(this);
72+
}
73+
74+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright (C) 2019 OnGres, Inc.
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
package io.stackgres.common.crd.storages;
7+
8+
import java.util.Objects;
9+
10+
import com.fasterxml.jackson.annotation.JsonIgnore;
11+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
12+
import com.fasterxml.jackson.annotation.JsonInclude;
13+
import io.quarkus.runtime.annotations.RegisterForReflection;
14+
import io.stackgres.common.StackGresUtil;
15+
import io.stackgres.common.validation.FieldReference;
16+
import io.stackgres.common.validation.FieldReference.ReferencedField;
17+
import io.stackgres.common.validation.ValidEnum;
18+
import io.sundr.builder.annotations.Buildable;
19+
import jakarta.validation.Valid;
20+
import jakarta.validation.constraints.AssertTrue;
21+
22+
@RegisterForReflection
23+
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
24+
@JsonIgnoreProperties(ignoreUnknown = true)
25+
@Buildable(editableEnabled = false, validationEnabled = false, generateBuilderPackage = false,
26+
lazyCollectionInitEnabled = false, lazyMapInitEnabled = false,
27+
builderPackage = "io.fabric8.kubernetes.api.builder")
28+
public class StorageEncryption {
29+
30+
@ValidEnum(enumClass = StorageEncryptionMethod.class, allowNulls = true,
31+
message = "mode can be sodium or openpgp")
32+
private String method;
33+
34+
@Valid
35+
private SodiumStorageEncryption sodium;
36+
37+
@Valid
38+
private OpenPgpStorageEncryption openpgp;
39+
40+
@ReferencedField("sodium")
41+
interface Sodium extends FieldReference { }
42+
43+
@ReferencedField("openpgp")
44+
interface Openpgp extends FieldReference { }
45+
46+
@JsonIgnore
47+
@AssertTrue(message = "sodium section is not specified.",
48+
payload = { Sodium.class })
49+
public boolean isSodiumRequired() {
50+
return method == null || !method.equals(StorageEncryptionMethod.SODIUM.toString()) || sodium != null;
51+
}
52+
53+
@JsonIgnore
54+
@AssertTrue(message = "openpgp section is not specified.",
55+
payload = { Openpgp.class })
56+
public boolean isOpenpgpRequired() {
57+
return method == null || !method.equals(StorageEncryptionMethod.OPENPGP.toString()) || openpgp != null;
58+
}
59+
60+
@JsonIgnore
61+
@AssertTrue(message = "sodium and openpgp sections are mutually exclusive.",
62+
payload = { Openpgp.class, Sodium.class })
63+
public boolean isEncryptionMethodSectionsMutuallyExclusive() {
64+
return method == null
65+
|| (sodium == null && openpgp == null)
66+
|| (sodium == null && openpgp != null)
67+
|| (sodium != null && openpgp == null);
68+
}
69+
70+
public String getMethod() {
71+
return method;
72+
}
73+
74+
public void setMethod(String method) {
75+
this.method = method;
76+
}
77+
78+
public SodiumStorageEncryption getSodium() {
79+
return sodium;
80+
}
81+
82+
public void setSodium(SodiumStorageEncryption sodium) {
83+
this.sodium = sodium;
84+
}
85+
86+
public OpenPgpStorageEncryption getOpenpgp() {
87+
return openpgp;
88+
}
89+
90+
public void setOpenpgp(OpenPgpStorageEncryption openpgp) {
91+
this.openpgp = openpgp;
92+
}
93+
94+
@Override
95+
public int hashCode() {
96+
return Objects.hash(method, openpgp, sodium);
97+
}
98+
99+
@Override
100+
public boolean equals(Object obj) {
101+
if (this == obj) {
102+
return true;
103+
}
104+
if (!(obj instanceof StorageEncryption)) {
105+
return false;
106+
}
107+
StorageEncryption other = (StorageEncryption) obj;
108+
return Objects.equals(method, other.method) && Objects.equals(openpgp, other.openpgp)
109+
&& Objects.equals(sodium, other.sodium);
110+
}
111+
112+
@Override
113+
public String toString() {
114+
return StackGresUtil.toPrettyYaml(this);
115+
}
116+
117+
}

0 commit comments

Comments
 (0)