Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Challenge 44&45: Vault Metadata challenge #1147

Merged
merged 34 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a749a5f
Prework for #719
commjoen Dec 15, 2023
ded69af
Merge branch 'master' into feature-vault-challenge
commjoen Dec 17, 2023
1926c79
Updated dep version
commjoen Dec 17, 2023
6936a78
building out basics for challenge 43
commjoen Dec 17, 2023
fe35f81
building out basics for challenge 44
commjoen Dec 17, 2023
ca62d40
feat: add Vault test container
Dec 19, 2023
5088f2f
Merge branch 'master' into feature-vault-challenge
commjoen Dec 19, 2023
b3755f2
Merge branch 'master' into feature-vault-challenge
commjoen Dec 30, 2023
ba1a88b
fix spotbug
commjoen Dec 30, 2023
25fb604
Add first texts
commjoen Dec 30, 2023
23fa033
Extend first test and see issue
commjoen Dec 30, 2023
8a66b9a
Route vault container test properly
commjoen Jan 6, 2024
15f463c
Fixed test
commjoen Jan 6, 2024
62d1c04
added next challenge
commjoen Jan 6, 2024
774f3f6
Merge branch 'master' into feature-vault-challenge
commjoen Jan 7, 2024
31fdc9c
added first integration parameters
commjoen Jan 7, 2024
ed3f70d
remove duplicate dep definition
commjoen Jan 7, 2024
164ea86
added challenge45 setup
commjoen Jan 7, 2024
2e9cd58
fix for spotbugs
commjoen Jan 7, 2024
bfed6c7
Fix final tests and configs
commjoen Jan 8, 2024
6d0bddb
first steps for k8s setup
commjoen Jan 8, 2024
853e63a
Update POM file with new version: challenge45-2
commjoen Jan 8, 2024
41a0749
Update POM file with new version: challenge45-3
commjoen Jan 8, 2024
b5d42bb
Update POM file with new version: challenge45-4
commjoen Jan 8, 2024
ad63417
Update POM file with new version: challenge45-5
commjoen Jan 8, 2024
17f44ad
Apply suggestions from code review
commjoen Jan 8, 2024
522938c
Merge branch 'master' into feature-vault-challenge
commjoen Jan 12, 2024
527dddb
attempt to fix bena issue
commjoen Jan 13, 2024
3eb52f8
fix: remove VaultConfig
Jan 13, 2024
0d2d287
Merge branch 'master' into feature-vault-challenge
commjoen Jan 13, 2024
f782b2d
Update POM file with new version: challenge45-7
commjoen Jan 13, 2024
7c1ee26
audit log instructions
commjoen Jan 13, 2024
0dcd518
Finalize vault setup and extra user
commjoen Jan 14, 2024
71a4c95
Finalize vault setup and extra user
commjoen Jan 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/scripts/.bash_history
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ rm -rf jdk-18_linux-x64_bin.deb
git rebase -i main
git rebase -i master
git stash
export tempPassword="XvAn9Kcj4XKXBFfkL0IBttcYp8GmZq7JuPjIjghfDZw="
export tempPassword="T/8yzIOE0Xz3RIxjA2HMyncgmhUoZsHZLW6lQVj5yV4="
mvn run tempPassword
k6
npx k6
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,9 @@ If you want to dev without a Vault instance, use additionally the `without-vault
./mvnw spring-boot:run -Dspring-boot.run.profiles=local,without-vault
```

Want to push a container? See `.github/scripts/docker-create-and-push.sh` for a script that generates and pushes all containers. Do not forget to rebuild the app before composing the container
Want to push a container? See `.github/scripts/docker-create-and-push.sh` for a script that generates and pushes all containers. Do not forget to rebuild the app before composing the container.

Want to check why something in vault is not working in kubernetes? Do `kubectl exec vault-0 -n vault -- vault audit enable file file_path=stdout`.

### Dependency management

Expand Down
44 changes: 42 additions & 2 deletions k8s-vault-minkube-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ else
helm repo add hashicorp https://helm.releases.hashicorp.com
fi
kubectl create ns vault
helm upgrade --install vault hashicorp/vault --version 0.23.0 --namespace vault --values k8s/helm-vault-values.yml
helm upgrade --install vault hashicorp/vault --version 0.27.0 --namespace vault --values k8s/helm-vault-values.yml

isvaultrunning=$(kubectl get pods -n vault --field-selector=status.phase=Running)
while [[ $isvaultrunning != *"vault-0"* ]]; do echo "waiting for Vault1" && sleep 2 && isvaultrunning=$(kubectl get pods -n vault --field-selector=status.phase=Running); done
Expand Down Expand Up @@ -81,26 +81,66 @@ kubectl exec vault-0 -n vault -- vault secrets enable -path=secret kv-v2
echo "Putting a secret in"
kubectl exec vault-0 -n vault -- vault kv put secret/secret-challenge vaultpassword.password="$(openssl rand -base64 16)"

echo "Putting a subkey issue in"
kubectl exec vault-0 -n vault -- vault kv put secret/wrongsecret aaaauser."$(openssl rand -base64 8)"="$(openssl rand -base64 16)"

echo "Oepsi metadata"
kubectl exec vault-0 -n vault -- vault kv metadata put -mount=secret -custom-metadata=secret="$(openssl rand -base64 16)" wrongsecret

echo "Enable k8s auth"
kubectl exec vault-0 -n vault -- vault auth enable kubernetes

echo "Writing k8s auth config"

kubectl exec vault-0 -n vault -- /bin/sh -c 'vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'

kubectl exec vault-0 -n vault -- vault audit enable file file_path=stdout

echo "Writing policy for secret-challenge"
kubectl exec vault-0 -n vault -- /bin/sh -c 'vault policy write secret-challenge - <<EOF
path "secret/data/secret-challenge" {
capabilities = ["read"]
}
path "secret/metadata/wrongsecret" {
capabilities = ["read", "list" ]
}
path "secret/subkeys/wrongsecret" {
capabilities = ["read", "list" ]
}
path "secret/data/wrongsecret" {
capabilities = ["read", "list" ]
}
path "secret/data/application" {
capabilities = ["read"]
}
EOF'

kubectl exec vault-0 -n vault -- /bin/sh -c 'vault policy write standard_sre - <<EOF
path "secret/data/secret-challenge" {
capabilities = ["list"]
}
path "secret/" {
capabilities = ["list"]
}
path "secret/*" {
capabilities = ["list"]
}
path "secret/*/subkeys/"{
capabilities = ["list", "read"]
}
path "secret/*/subkeys/*"{
capabilities = ["list", "read"]
}
path "secret/metadata/*"{
capabilities = ["list", "read"]
}
EOF'

kubectl exec vault-0 -n vault -- vault auth enable userpass
kubectl exec vault-0 -n vault -- vault write auth/userpass/users/helper password=foo policies=standard_sre

echo "Write secrets for secret-challenge"
kubectl exec vault-0 -n vault -- vault write auth/kubernetes/role/secret-challenge \
bound_service_account_names=vault \
Expand Down
2 changes: 1 addition & 1 deletion k8s/secret-challenge-vault-deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ spec:
runAsNonRoot: true
serviceAccountName: vault
containers:
- image: jeroenwillemsen/wrongsecrets:1.8.1-k8s-vault
- image: jeroenwillemsen/wrongsecrets:challenge45-7-k8s-vault
imagePullPolicy: IfNotPresent
name: secret-challenge
securityContext:
Expand Down
30 changes: 25 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
</dependency>

<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-dependencies</artifactId>
Expand Down Expand Up @@ -123,11 +129,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
Expand All @@ -148,6 +149,20 @@
<version>${spring-security.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>vault</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand Down Expand Up @@ -278,6 +293,11 @@
<version>1.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.vault</groupId>
<artifactId>spring-vault-core</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>

<build>
Expand Down
42 changes: 40 additions & 2 deletions scripts/install-vault.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if [ $? == 0 ]; then
echo "Vault ns is already there"
else
kubectl create ns vault
helm upgrade --install vault hashicorp/vault --version 0.23.0 --namespace vault --values ../k8s/helm-vault-values.yml
helm upgrade --install vault hashicorp/vault --version 0.27.0 --namespace vault --values ../k8s/helm-vault-values.yml
fi


Expand Down Expand Up @@ -49,11 +49,16 @@ kubectl exec vault-0 -n vault -- vault secrets enable -path=secret kv-v2
echo "Putting a secret in"
kubectl exec vault-0 -n vault -- vault kv put secret/secret-challenge vaultpassword.password="$(openssl rand -base64 16)"

echo "Putting a subkey issue in"
kubectl exec vault-0 -n vault -- vault kv put secret/wrongsecret aaaauser."$(openssl rand -base64 8)"="$(openssl rand -base64 16)"

echo "Oepsi metadata"
kubectl exec vault-0 -n vault -- vault kv metadata put -mount=secret -custom-metadata=secret="$(openssl rand -base64 16)" wrongsecret

echo "Enable k8s auth"
kubectl exec vault-0 -n vault -- vault auth enable kubernetes

echo "Writing k8s auth config"

kubectl exec vault-0 -n vault -- /bin/sh -c 'vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
Expand All @@ -64,11 +69,44 @@ kubectl exec vault-0 -n vault -- /bin/sh -c 'vault policy write secret-challenge
path "secret/data/secret-challenge" {
capabilities = ["read"]
}
path "secret/metadata/wrongsecret" {
capabilities = ["read", "list" ]
}
path "secret/subkeys/wrongsecret" {
capabilities = ["read", "list" ]
}
path "secret/data/wrongsecret" {
capabilities = ["read", "list" ]
}
path "secret/data/application" {
capabilities = ["read"]
}
EOF'

kubectl exec vault-0 -n vault -- /bin/sh -c 'vault policy write standard_sre - <<EOF
path "secret/data/secret-challenge" {
capabilities = ["list"]
}
path "secret/" {
capabilities = ["list"]
}
path "secret/*" {
capabilities = ["list"]
}
path "secret/*/subkeys/"{
capabilities = ["list", "read"]
}
path "secret/*/subkeys/*"{
capabilities = ["list", "read"]
}
path "secret/metadata/*"{
capabilities = ["list", "read"]
}
EOF'

kubectl exec vault-0 -n vault -- vault auth enable userpass
kubectl exec vault-0 -n vault -- vault write auth/userpass/users/helper password=foo policies=standard_sre

echo "Write secrets for secret-challenge"
kubectl exec vault-0 -n vault -- vault write auth/kubernetes/role/secret-challenge \
bound_service_account_names=vault \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.owasp.wrongsecrets.challenges.kubernetes;

import com.google.common.base.Strings;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.owasp.wrongsecrets.challenges.FixedAnswerChallenge;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.vault.config.VaultProperties;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.vault.core.*;
import org.springframework.vault.support.Versioned;

/**
* This challenge is about having a metadata of secrets stored in a misconfigured Hashicorp Vault.
*/
@Component
@Slf4j
public class MetaDataChallenge extends FixedAnswerChallenge {

private final String vaultPasswordString;
private final VaultTemplate vaultTemplate;

private final VaultProperties.AuthenticationMethod authenticationMethod;

public MetaDataChallenge(
@Value("${vaultpassword}") String vaultPasswordString,
@Nullable VaultTemplate vaultTemplate,
@Value("${spring.cloud.vault.authentication}")
VaultProperties.AuthenticationMethod vaultAuthmethod) {
this.vaultPasswordString = vaultPasswordString;
this.vaultTemplate = vaultTemplate;
this.authenticationMethod = vaultAuthmethod;
}

public String getAnswer() {
try {
if (VaultProperties.AuthenticationMethod.NONE.equals(authenticationMethod)
|| vaultTemplate == null) {
log.warn("Vault not setup for challenge 44");
return vaultPasswordString;
}
VaultVersionedKeyValueOperations versionedOperations =
vaultTemplate.opsForVersionedKeyValue("secret");
Versioned<Map<String, Object>> versioned = versionedOperations.get("wrongsecret");
if (versioned == null) {
return vaultPasswordString;
}
var metadata = versioned.getMetadata();
if (metadata == null) {
return vaultPasswordString;
}
var customMetadata = metadata.getCustomMetadata();
if (!customMetadata.isEmpty()) {
String customMedataSecret = customMetadata.get("secret");
if (Strings.isNullOrEmpty(customMedataSecret)) {
return vaultPasswordString;
}
return customMedataSecret;
}
} catch (Exception e) {
log.warn("Exception during execution of challenge44", e);
}
return vaultPasswordString;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.owasp.wrongsecrets.challenges.kubernetes;

import java.util.Map;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.owasp.wrongsecrets.challenges.FixedAnswerChallenge;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.vault.config.VaultProperties;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.vault.core.VaultTemplate;
import org.springframework.vault.core.VaultVersionedKeyValueOperations;
import org.springframework.vault.support.Versioned;

@Component
@Slf4j
public class VaultSubKeyChallenge extends FixedAnswerChallenge {

private final String vaultPasswordString;
private final VaultTemplate vaultTemplate;

private final VaultProperties.AuthenticationMethod authenticationMethod;

public VaultSubKeyChallenge(
@Value("${vaultpassword}") String vaultPasswordString,
@Nullable VaultTemplate vaultTemplate,
@Value("${spring.cloud.vault.authentication}")
VaultProperties.AuthenticationMethod vaultAuthmethod) {
this.vaultPasswordString = vaultPasswordString;
this.vaultTemplate = vaultTemplate;
this.authenticationMethod = vaultAuthmethod;
}

@Override
public String getAnswer() {
try {
if (VaultProperties.AuthenticationMethod.NONE.equals(authenticationMethod)
|| vaultTemplate == null) {
log.warn("Vault not setup for challenge 45");
return vaultPasswordString;
}
VaultVersionedKeyValueOperations versionedOperations =
vaultTemplate.opsForVersionedKeyValue("secret");
Versioned<Map<String, Object>> versioned = versionedOperations.get("wrongsecret");
if (versioned == null) {
return vaultPasswordString;
}
Optional<String> first = versioned.getRequiredData().keySet().stream().findFirst();
return first.orElse(vaultPasswordString);

} catch (Exception e) {
log.warn("Exception during execution of challenge45", e);
}
return vaultPasswordString;
}
}
6 changes: 6 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ CHALLENGE33=if_you_see_this_please_use_k8s
ARG_BASED_PASSWORD=if_you_see_this_please_use_docker_instead
DOCKER_ENV_PASSWORD=if_you_see_this_please_use_docker_instead
vaultpassword=if_you_see_this_please_use_K8S_and_Vault
spring.cloud.vault.uri=https://tobediefined.org
spring.cloud.vault.authentication=NONE
spring.cloud.vault.role=none
spring.cloud.vault.kubernetes-path=none
spring.cloud.vault.scheme=https://tobediefined.org
spring.cloud.vault.kubernetes.service-account-token-file="none"
default_aws_value=if_you_see_this_please_use_AWS_Setup
default_aws_value_challenge_9=if_you_see_this_please_use_AWS_Setup
default_aws_value_challenge_10=if_you_see_this_please_use_AWS_Setup
Expand Down
9 changes: 9 additions & 0 deletions src/main/resources/explanations/challenge44.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
=== Vault Metadata Challenge

Secrets management systems now often have metadata support for their secrets! This is awesome, as it allows you to enrich the secret with contextual data further, making it easier to remember the secret.

But what if you put confidential/secret information into a secret by mistake?

A developer has put secret metadata on a `wrongsecret` in Vault. Can you find it?

Tip: take a look at the policies when vault is installed; you can see that the application is only allowed to use the metadata ;-).
Loading
Loading