Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PYTEST_ADDOPTS=--no-cov
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ vault.yml
server-chain.crt
client.crt
client.key
.vscode/
1 change: 0 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

@pytest.fixture(autouse=True)
def isolate_tests():

for key in os.environ:
if key.startswith(settings.ENV_PREFIX):
os.environ.pop(key)
Expand Down
185 changes: 170 additions & 15 deletions tests/integration/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,28 @@

import pytest

import yaml
import vault_cli
from vault_cli import cli

@pytest.fixture()
def kvv2_config(tmp_path):
with tmp_path.joinpath("vault.kv2.yml").open("w") as fw:
yaml.dump({"url": "https://localhost:8443", "base_path": "secret/", "ca_bundle": "server-chain.crt", "token": "some-token"}, fw)
os.environ["TEST_INTEGRATION_CONFIG_FILE"] = str(tmp_path.joinpath("vault.kv2.yml"))
yield str(tmp_path.joinpath("vault.kv2.yml"))

@pytest.fixture()
def kvv1_config(tmp_path):
with tmp_path.joinpath("vault.kv1.yml").open("w") as fw:
yaml.dump({"url": "https://localhost:8443", "base_path": "secretkvv1/", "ca_bundle": "server-chain.crt", "token": "some-token"}, fw)
os.environ["TEST_INTEGRATION_CONFIG_FILE"] = str(tmp_path.joinpath("vault.kv1.yml"))
yield str(tmp_path.joinpath("vault.kv1.yml"))

def call(cli_runner, *args, **kwargs):
call = cli_runner.invoke(cli.cli, *args, **kwargs)
_args = list(args)
_args[0] = ["--config-file", os.environ.get("TEST_INTEGRATION_CONFIG_FILE")] + _args[0]
call = cli_runner.invoke(cli.cli, *tuple(_args), **kwargs)
assert call.exit_code == 0, call.output
return call

Expand All @@ -20,7 +36,7 @@ def clean_vault(cli_runner):
call(cli_runner, ["delete-all", "-f"])


def test_integration_cli(cli_runner, clean_vault):
def test_integration_cli_kvv1(kvv1_config, cli_runner, clean_vault):

call(cli_runner, ["set", "a", "value=b"])

Expand Down Expand Up @@ -80,7 +96,7 @@ def test_integration_cli(cli_runner, clean_vault):

call(cli_runner, ["delete", "c/d", "foo"])

result = cli_runner.invoke(cli.cli, ["get", "c/d", "foo"])
result = cli_runner.invoke(cli.cli, ["--config-file", kvv1_config ,"get", "c/d", "foo"])
assert result.exit_code == 1
assert (
result.output
Expand All @@ -99,9 +115,9 @@ def test_integration_cli(cli_runner, clean_vault):
assert call(cli_runner, ["lookup-token"]).output.startswith("---\nauth:")


def test_integration_lib(clean_vault):
def test_integration_lib_kvv1(kvv1_config, clean_vault):

client = vault_cli.get_client()
client = vault_cli.get_client(config_file=kvv1_config)

client.set_secret("a", {"value": "b"})

Expand Down Expand Up @@ -143,11 +159,128 @@ def test_integration_lib(clean_vault):
assert client.get_secret("novalue") == {"password": "pass", "username": "name"}


def test_env_var_config():
def test_integration_cli_kvv2(kvv2_config, cli_runner, clean_vault):

call(cli_runner, ["set", "a", "value=b"])

assert call(cli_runner, ["get", "a"]).output == "---\nvalue: b\n"

assert call(cli_runner, ["get", "a", "--yaml"]).output == "---\nvalue: b\n"

assert call(cli_runner, ["get", "a", "value"]).output == "b\n"

assert call(cli_runner, ["get", "a", "value", "--yaml"]).output == "--- b\n...\n"

call(cli_runner, ["set", "c", "--file=-"], input="{'key1':'val1', 'key2':'val2'}")

assert call(cli_runner, ["get", "c"]).output == "---\nkey1: val1\nkey2: val2\n"

# Both testing it and using it to clean the vault
call(cli_runner, ["delete-all", "--force"])

assert call(cli_runner, ["list"]).output == "\n"

call(cli_runner, ["set", "a", "value=b"])

assert call(cli_runner, ["list"]).output == "a\n"

call(cli_runner, ["set", "c/d", "foo=e", "bar=f"])

assert call(cli_runner, ["get", "c/d", "foo"]).output == "e\n"

assert call(cli_runner, ["list"]).output == "a\nc/\n"

assert call(cli_runner, ["list", "c"]).output == "d\n"

assert call(cli_runner, ["get-all", ""]).output == (
"""---
a:
value: b
c/d:
bar: f
foo: e
"""
)

assert call(cli_runner, ["get-all", "--no-flat"]).output == (
"""---
a:
value: b
c:
d:
bar: f
foo: e
"""
)

call(cli_runner, ["delete", "a"])

assert call(cli_runner, ["list"]).output == "c/\n"

call(cli_runner, ["delete", "c/d", "foo"])

result = cli_runner.invoke(cli.cli, ["--config-file", kvv2_config ,"get", "c/d", "foo"])
assert result.exit_code == 1
assert (
result.output
== """Error: VaultSecretNotFound: Secret not found
Key 'foo' not found in secret at path '/secret/c/d'
KeyError: 'foo'
"""
)

assert call(cli_runner, ["list"]).output == "c/\n"

call(cli_runner, ["delete-all", "--force"])

assert call(cli_runner, ["list"]).output == "\n"

assert call(cli_runner, ["lookup-token"]).output.startswith("---\nauth:")


def test_integration_lib_kvv2(kvv2_config, clean_vault):

client = vault_cli.get_client(config_file=kvv2_config)

client.set_secret("a", {"value": "b"})

assert client.get_secret("a") == {"value": "b"}

assert "a" in list(client.delete_all_secrets(""))

assert client.list_secrets("") == []

client.set_secret("a", {"value": "b"})

assert client.list_secrets("") == ["a"]

client.set_secret("c/d", {"name": "e"})

assert client.get_secret("c/d") == {"name": "e"}

assert client.list_secrets("") == ["a", "c/"]

assert client.list_secrets("c") == ["d"]

assert client.get_all_secrets("") == {
"a": {"value": "b"},
"c": {"d": {"name": "e"}},
}

client.delete_secret("a")

assert client.list_secrets("") == ["c/"]

assert list(client.delete_all_secrets("")) == ["c/d"]

assert client.lookup_token()["data"]


def test_env_var_config(kvv1_config):
# Test env var config
os.environ["VAULT_CLI_TOKEN"] = "some-other-token"
with pytest.raises(vault_cli.VaultAPIException):
vault_cli.get_client().set_secret("a", {"name": "value"})
vault_cli.get_client(config_file=kvv1_config).set_secret("a", {"name": "value"})


def check_call(command):
Expand All @@ -162,9 +295,19 @@ def set_ACD(cli_runner, clean_vault):
call(cli_runner, ["set", "C/D", "username=foo", "password=bar"])


def test_boostrap_env(set_ACD):
def test_boostrap_env_kvv1(kvv1_config, set_ACD, cli_runner):
env = subprocess.check_output(
f"python -m vault_cli --config-file {kvv1_config} env -p A -p C -p C/D:password=PASS -- env".split()
)

assert b"A_VALUE=B\n" in env
assert b"D_USERNAME=foo\n" in env
assert b"D_PASSWORD=bar\n" in env
assert b"PASS=bar\n" in env

def test_boostrap_env_kvv2(kvv2_config, set_ACD, cli_runner):
env = subprocess.check_output(
"vault-cli env -p A -p C -p C/D:password=PASS -- env".split()
f"python -m vault_cli --config-file {kvv2_config} env -p A -p C -p C/D:password=PASS -- env".split()
)

assert b"A_VALUE=B\n" in env
Expand All @@ -173,7 +316,7 @@ def test_boostrap_env(set_ACD):
assert b"PASS=bar\n" in env


def test_ssh(clean_vault, cli_runner):
def test_ssh(kvv1_config, clean_vault, cli_runner):
# In case this is not sufficienlty explicit that this is a test key, then:
#
# THIS IS A TEST KEY, DO NOT USE IN THE REAL WORLD
Expand All @@ -191,18 +334,17 @@ def test_ssh(clean_vault, cli_runner):
ssh_passphrase = "foobar"
call(
cli_runner,
["set", "ssh_key", f"private={ssh_private}", f"passphrase={ssh_passphrase}"],
["--config-file", kvv1_config, "set", "ssh_key", f"private={ssh_private}", f"passphrase={ssh_passphrase}"],
)
identities = subprocess.run(
"vault-cli ssh --key ssh_key:private --passphrase ssh_key:passphrase "
f"python -m vault_cli --config-file {kvv1_config} ssh --key ssh_key:private --passphrase ssh_key:passphrase "
"-- ssh-add -L".split(),
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
assert ssh_public in identities.stdout.decode("utf-8")
assert "Identity added" not in identities.stdout.decode("utf-8")
assert identities.stderr.decode("utf-8") == ""


@pytest.fixture
Expand All @@ -220,8 +362,21 @@ def umask():
("--umask=000 ", "0o666"),
],
)
def test_umask(set_ACD, umask, tmp_path, flag, expected):
def test_umask_kvv1(kvv1_config, set_ACD, umask, tmp_path, flag, expected):
path = tmp_path / "test_boostrap_env"
# umask = 0o000 => permissions = 0o666 - 0o000 = 0o666
subprocess.check_output(f"python -m vault_cli --config-file {kvv1_config} {flag}get A -o {path}".split())
assert oct(path.stat().st_mode & 0o777) == expected

@pytest.mark.parametrize(
"flag, expected",
[
("", "0o600"),
("--umask=000 ", "0o666"),
],
)
def test_umask_kvv2(kvv2_config, set_ACD, umask, tmp_path, flag, expected):
path = tmp_path / "test_boostrap_env"
# umask = 0o000 => permissions = 0o666 - 0o000 = 0o666
subprocess.check_output(f"vault-cli {flag}get A -o {path}".split())
subprocess.check_output(f"python -m vault_cli --config-file {kvv2_config} {flag}get A -o {path}".split())
assert oct(path.stat().st_mode & 0o777) == expected
14 changes: 12 additions & 2 deletions tests/unit/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@

# To debug cli_runner.invoke, add the argument "catch_exceptions=False"

@pytest.fixture()
def kvv1_config(tmp_path):
with tmp_path.joinpath("vault.kv1.yml").open("w") as fw:
yaml.dump({"url": "https://localhost:8443", "base_path": "secretkvv1/", "ca_bundle": "server-chain.crt", "token": "some-token"}, fw)
os.environ["TEST_INTEGRATION_CONFIG_FILE"] = str(tmp_path.joinpath("vault.kv1.yml"))
yield str(tmp_path.joinpath("vault.kv1.yml"))

def test_options(cli_runner, mocker):
client = mocker.patch("vault_cli.client.get_client_class").return_value
Expand All @@ -22,6 +28,8 @@ def test_options(cli_runner, mocker):
[
"--base-path",
"bla",
"--namespace",
"foobar",
"--ca-bundle",
"yay",
"--login-cert",
Expand Down Expand Up @@ -51,6 +59,7 @@ def test_options(cli_runner, mocker):
"password",
"safe_write",
"token",
"namespace",
"url",
"username",
"verify",
Expand All @@ -64,6 +73,7 @@ def test_options(cli_runner, mocker):
assert kwargs["url"] == "https://foo"
assert kwargs["username"] == "user"
assert kwargs["verify"] is True
assert kwargs["namespace"] is "foobar"


@pytest.fixture
Expand Down Expand Up @@ -351,9 +361,9 @@ def test_env_error(cli_runner, vault_with_token, mocker):
exec_command.assert_not_called()


def test_env_envvar_format_error(cli_runner):
def test_env_envvar_format_error(kvv1_config, cli_runner):
result = cli_runner.invoke(
cli.cli, ["env", "--envvar", ":foo", "--", "echo", "yay"]
cli.cli, ["--config-file", kvv1_config, "env", "--envvar", ":foo", "--", "echo", "yay"]
)

assert result.exit_code != 0
Expand Down
1 change: 1 addition & 0 deletions tests/unit/test_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def _authenticate_certificate(self, *args, **kwargs):
"url": "yay",
"login_cert": "a",
"login_cert_key": "b",
"namespace": None
}


Expand Down
Loading