Skip to content

Commit

Permalink
[ciphering] integrate codec-core from yupiik tools to placeholders to…
Browse files Browse the repository at this point in the history
… support a default ciphering algorithm
  • Loading branch information
rmannibucau committed Dec 26, 2023
1 parent 3248a2c commit d1af132
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 176 deletions.
6 changes: 6 additions & 0 deletions bundlebee-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@
<version>${yupiik-logging.version}</version>
</dependency>

<dependency>
<groupId>io.yupiik.maven</groupId>
<artifactId>codec-core</artifactId>
<version>${yupiik-tools.version}</version>
</dependency>

<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-junit5</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2021-2023 - Yupiik SAS - https://www.yupiik.com
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.yupiik.bundlebee.core.command.impl;

import io.yupiik.bundlebee.core.command.Executable;
import io.yupiik.bundlebee.core.configuration.Description;
import io.yupiik.tools.codec.simple.SimpleCodec;
import io.yupiik.tools.codec.simple.SimpleCodecConfiguration;
import lombok.extern.java.Log;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import java.util.concurrent.CompletionStage;

import static java.util.concurrent.CompletableFuture.completedFuture;

@Log
@Dependent
public class CipherCommand implements Executable {
@Inject
@Description("Master password..")
@ConfigProperty(name = "bundlebee.cipher.masterPassword", defaultValue = UNSET)
private String masterPassword;

@Inject
@Description("Value to cipher.")
@ConfigProperty(name = "bundlebee.cipher.value", defaultValue = UNSET)
private String value;

@Override
public String name() {
return "cipher";
}

@Override
public String description() {
return "Enables to cipher a value using `AES/CBC/PKCS5Padding` algorithm with a master password. It can then be used as a placeholder with the syntax `{{bundlebee-decipher:{{my.master.password}},$cipheredValue}}`.";
}

@Override
public CompletionStage<?> execute() {
if (UNSET.equals(value) || UNSET.equals(masterPassword)) {
throw new IllegalArgumentException("Missing master password or value to decipher, ensure both are set.");
}
// not a lambda to fail if the ciphering fails even if it is not logged
log.info(new SimpleCodec(SimpleCodecConfiguration.builder().masterPassword(masterPassword).build()).encrypt(value.strip()));
return completedFuture(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2021-2023 - Yupiik SAS - https://www.yupiik.com
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.yupiik.bundlebee.core.command.impl;

import io.yupiik.bundlebee.core.command.Executable;
import io.yupiik.bundlebee.core.configuration.Description;
import io.yupiik.tools.codec.simple.SimpleCodec;
import io.yupiik.tools.codec.simple.SimpleCodecConfiguration;
import lombok.extern.java.Log;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import java.util.concurrent.CompletionStage;

import static java.util.concurrent.CompletableFuture.completedFuture;

@Log
@Dependent
public class DecipherCommand implements Executable {
@Inject
@Description("Master password..")
@ConfigProperty(name = "bundlebee.decipher.masterPassword", defaultValue = UNSET)
private String masterPassword;

@Inject
@Description("Value to decipher.")
@ConfigProperty(name = "bundlebee.decipher.value", defaultValue = UNSET)
private String value;

@Override
public String name() {
return "decipher";
}

@Override
public String description() {
return "Enables to decipher a value using `AES/CBC/PKCS5Padding` algorithm with a master password.";
}

@Override
public CompletionStage<?> execute() {
if (UNSET.equals(value) || UNSET.equals(masterPassword)) {
throw new IllegalArgumentException("Missing master password or value to decipher, ensure both are set.");
}
// not a lambda to fail if the deciphering fails even if it is not logged
log.info(new SimpleCodec(SimpleCodecConfiguration.builder().masterPassword(masterPassword).build()).decrypt(value.strip()));
return completedFuture(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import io.yupiik.bundlebee.core.kube.KubeClient;
import io.yupiik.bundlebee.core.qualifier.BundleBee;
import io.yupiik.bundlebee.core.service.Maven;
import io.yupiik.tools.codec.simple.SimpleCodec;
import io.yupiik.tools.codec.simple.SimpleCodecConfiguration;
import lombok.extern.java.Log;
import org.eclipse.microprofile.config.Config;

Expand Down Expand Up @@ -234,6 +236,9 @@ protected String doSubstitute(final AtomicReference<Substitutor> self, final Con
throw new IllegalStateException(e);
}
}
if (placeholder.startsWith("bundlebee-decipher:")) {
return doDecipher(placeholder);
}
if (placeholder.startsWith("bundlebee-uppercase:")) {
return placeholder.substring("bundlebee-uppercase:".length()).toUpperCase(ROOT);
}
Expand Down Expand Up @@ -315,6 +320,19 @@ protected String doSubstitute(final AtomicReference<Substitutor> self, final Con
return config.getOptionalValue(placeholder, String.class).orElse(null);
}

private String doDecipher(final String string) {
final var confAndValue = string.substring("bundlebee-decipher:".length());
final int sep = confAndValue.lastIndexOf(','); // last cause value is base64 encoded so it enables a master password placeholder with a comma
if (sep < 0) {
throw new IllegalArgumentException("Usage: {{bundlebee-decipher:$masterKeyPlaceholder,$cipheredValue}}");
}
// todo: enable to cache the codec but should only be for a short duration or single apply/delete command
return new SimpleCodec(SimpleCodecConfiguration.builder()
.masterPassword(confAndValue.substring(0, sep))
.build())
.decrypt(confAndValue.substring(sep + 1).strip());
}

private byte[] readResource(final String text, final String prefix) throws IOException {
final var name = text.substring(prefix.length());
final var path = Path.of(name);
Expand Down
Loading

0 comments on commit d1af132

Please sign in to comment.