diff --git a/.travis.yml b/.travis.yml index 7d1b295..9b1db4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,27 +22,54 @@ env: global: - NOMAD_IP="127.0.0.1" - NOMAD_PORT="4646" + - VAULT_ADDR="http://127.0.0.1:8200" + - VAULT_TEST="true" matrix: - - NOMAD_VERSION="0.3.2" - - NOMAD_VERSION="0.4.1" - - NOMAD_VERSION="0.5.6" - - NOMAD_VERSION="0.6.0" - - NOMAD_VERSION="0.7.1" - - NOMAD_VERSION="0.8.1" - - NOMAD_VERSION="0.8.3" -before_install: -- curl -L -o /tmp/nomad_${NOMAD_VERSION}_linux_amd64.zip https://releases.hashicorp.com/nomad/${NOMAD_VERSION}/nomad_${NOMAD_VERSION}_linux_amd64.zip -- yes | unzip -d /tmp /tmp/nomad_${NOMAD_VERSION}_linux_amd64.zip -- MAJOR_VERSION=`echo ${NOMAD_VERSION} | cut -d "." -f 2` -- if [[ ${MAJOR_VERSION} -gt 6 ]]; then echo "Nomad version $NOMAD_VERSION supports acls";export ACL_ENABLED="--acl-enabled"; else echo "Nomad version $NOMAD_VERSION";export ACL_ENABLED=""; fi -- /tmp/nomad agent -dev -bind ${NOMAD_IP} -node pynomad1 ${ACL_ENABLED} > /dev/null 2>&1 & -- sleep 30 + - NOMAD_VERSION="0.3.2";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.4.1";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.5.6";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.6.0";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.7.1";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.8.1";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.8.3";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.8.4";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.8.5";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.8.6";VAULT_VERSION="0.8.0" + - NOMAD_VERSION="0.3.2";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.4.1";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.5.6";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.6.0";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.7.1";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.8.1";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.8.3";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.8.4";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.8.5";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.8.6";VAULT_VERSION="0.9.0" + - NOMAD_VERSION="0.3.2";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.4.1";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.5.6";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.6.0";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.7.1";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.8.1";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.8.3";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.8.4";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.8.5";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.8.6";VAULT_VERSION="0.10.0" + - NOMAD_VERSION="0.3.2";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.4.1";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.5.6";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.6.0";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.7.1";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.8.1";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.8.3";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.8.4";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.8.5";VAULT_VERSION="0.11.4" + - NOMAD_VERSION="0.8.6";VAULT_VERSION="0.11.4" install: - pip install -r requirements.txt -r requirements-dev.txt - pip install codecov before_script: - - /tmp/nomad init - - /tmp/nomad run -output example.nomad > example.json + - sudo ./start_daemons.sh script: - py.test --cov=nomad --cov-report=term-missing --runxfail tests/ after_success: diff --git a/README.md b/README.md index 91497aa..331c7bf 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,19 @@ NOMAD_TOKEN=xxxx-xxxx-xxxx-xxxx NOMAD_REGION=us-east-1a ``` +## With Vault integration. + +Vault info [:link:](vaultintegration.md) + +if you have configured a [Vault Integration ](https://www.nomadproject.io/docs/configuration/vault.html) to store your secrets. + +And you have configured: [`allow_unantenticated = false`](https://www.nomadproject.io/docs/configuration/vault.html#allow_unauthenticated) +see you must to export and send a valid `VAULT_TOKEN`. + +```bash +VAULT_TOKEN=xxxx-xxxx-xxxx-xxxx +``` + ## Class Dunders | Class | contains | len | getitem | iter | @@ -96,15 +109,29 @@ pip install -r requirements-dev.txt ``` ## Testing with vagrant and virtualbox + +- Define versions at vagrant file +- Execute tests ``` vagrant up --provider virtualbox -py.test --cov=nomad --cov-report=term-missing --runxfail tests/ +``` +- Destroy Vagrant +``` +vagrant destroy ``` ## Testing with nomad binary ``` -./nomad agent -dev -node pynomad1 --acl-enabled -NOMAD_IP=127.0.0.1 NOMAD_VERSION= py.test --cov=nomad --cov-report=term-missing --runxfail tests/ +export NOMAD_IP=127.0.0.1 +export NOMAD_VERSION= +export VAULT_VERSION= # should be higher than 0.6.2 +./start_daemons.sh +py.test --cov=nomad --cov-report=term-missing --runxfail tests/ +``` + +after make your tests, you can stop the necesary daemons with +``` +./stop_daemons.sh ``` - Examples diff --git a/Vagrantfile b/Vagrantfile index fafbb8c..b73c7da 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,18 +1,25 @@ # -*- mode: ruby -*- # vi: set ft=ruby : -IP = "192.168.33.10" -NOMAD_VERSION = "0.8.3" -NOMAD_PORT_GUEST = 4646 -NOMAD_PORT_HOST = 4646 +NOMAD_IP="192.168.33.10" +NOMAD_VERSION="0.8.6" +NOMAD_PORT_GUEST=4646 +NOMAD_PORT_HOST=4646 +VAULT_VERSION="0.11.4" +VAULT_PORT_GUEST=8200 +VAULT_PORT_HOST=8200 +VAULT_ADDR="http://127.0.0.1:8200" +VAULT_TEST="true" + Vagrant.configure(2) do |config| config.vm.box = "centos/7" config.vm.network "forwarded_port", guest: NOMAD_PORT_GUEST, host: NOMAD_PORT_HOST +config.vm.network "forwarded_port", guest: VAULT_PORT_GUEST, host: VAULT_PORT_HOST -config.vm.network "private_network", ip: "#{IP}" +config.vm.network "private_network", ip: "#{NOMAD_IP}" config.vm.provider "virtualbox" do |vb| vb.name = "python-nomad" @@ -22,8 +29,7 @@ end config.vm.provision "shell", inline: <<-SHELL -if [ ! -e /etc/yum.repos.d/docker.repo ] - then +if [ ! -e /etc/yum.repos.d/docker.repo ]; then tee /etc/yum.repos.d/docker.repo <<-EOF [dockerrepo] name=Docker Repository @@ -38,22 +44,26 @@ yum -y install docker-engine unzip wget net-tools usermod -aG docker vagrant systemctl enable docker; systemctl start docker -wget -q -P /tmp/ https://releases.hashicorp.com/nomad/#{NOMAD_VERSION}/nomad_#{NOMAD_VERSION}_linux_amd64.zip -yes | unzip -d /tmp /tmp/nomad_#{NOMAD_VERSION}_linux_amd64.zip +echo "pip for test inside the vagrant" +curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" +python get-pip.py +pip install -r /vagrant/requirements-dev.txt -if [ ! -f /usr/bin/nomad ] - then - cp /tmp/nomad /usr/bin/. -fi +cat << EOF > /tmp/environment.vars.sh +export NOMAD_IP="#{NOMAD_IP}" +export NOMAD_VERSION="#{NOMAD_VERSION}" +export NOMAD_PORT_GUEST="#{NOMAD_PORT_GUEST}" +export NOMAD_PORT_HOST="#{NOMAD_PORT_HOST}" +export VAULT_VERSION="#{VAULT_VERSION}" +export VAULT_ADDR="#{VAULT_ADDR}" +export VAULT_TEST="#{VAULT_TEST}" +EOF +chmod +x /tmp/environment.vars.sh +source /tmp/environment.vars.sh +cd /vagrant +./start_daemons.sh -if [ $(pgrep nomad) ] - then - echo "Nomad running" - else - echo "Starting Nomad" - nohup nomad agent -dev -bind #{IP} -node pynomad1 --acl-enabled > /dev/null 2>&1 & - sleep 30 -fi +py.test --cov=nomad --cov-report=term-missing --runxfail tests/ SHELL diff --git a/example_batch_parameterized.json b/example_batch_parameterized.json old mode 100644 new mode 100755 diff --git a/nomad/__init__.py b/nomad/__init__.py index 0eb04bf..0ef9834 100644 --- a/nomad/__init__.py +++ b/nomad/__init__.py @@ -10,11 +10,12 @@ def __init__(self, port=4646, address=os.getenv('NOMAD_ADDR', None), namespace=os.getenv('NOMAD_NAMESPACE', None), - token=os.getenv('NOMAD_TOKEN', None), - timeout=5, - region=os.getenv('NOMAD_REGION', None), - version='v1', - verify=False, + token=os.getenv('NOMAD_TOKEN', None), + vaulttoken=os.getenv('VAULT_TOKEN', None), + timeout=5, + region=os.getenv('NOMAD_REGION', None), + version='v1', + verify=False, cert=()): """ Nomad api client @@ -35,6 +36,9 @@ def __init__(self, be use to deploy or to ask info to nomad. - token (defaults to None), Specifies to append ACL token to the headers to make authentication on secured based nomad environemnts. + - vaulttoken (defaults to None), Specifies to append ACL token to the job and + make authentication on environemnts with allow_unantenticated = false, where + you must to send a valid vault token for policies. returns: Nomad api client object raises: @@ -50,6 +54,7 @@ def __init__(self, self.timeout = timeout self.version = version self.token = token + self.vaulttoken = vaulttoken self.verify = verify self.cert = cert self.__namespace = namespace @@ -60,6 +65,7 @@ def __init__(self, "port": self.port, "namespace": self.__namespace, "token": self.token, + "vaulttoken": self.vaulttoken, "timeout": self.timeout, "version": self.version, "verify": self.verify, @@ -103,6 +109,9 @@ def get_namespace(self): def get_token(self): return self.token + def get_vaulttoken(self): + return self.vaulttoken + @property def jobs(self): return self._jobs diff --git a/nomad/api/base.py b/nomad/api/base.py index cca3a09..5b88a8d 100644 --- a/nomad/api/base.py +++ b/nomad/api/base.py @@ -10,11 +10,12 @@ class Requester(object): ENDPOINT = "" - def __init__(self, address=None, uri='http://127.0.0.1', port=4646, namespace=None, token=None, timeout=5, version='v1', verify=False, cert=(), region=None, **kwargs): + def __init__(self, address=None, uri='http://127.0.0.1', port=4646, namespace=None, token=None, vaulttoken=None, timeout=5, version='v1', verify=False, cert=(), region=None, **kwargs): self.uri = uri self.port = port self.namespace = namespace self.token = token + self.vaulttoken = vaulttoken self.timeout = timeout self.version = version self.verify = verify @@ -99,6 +100,12 @@ def _request(self, method, endpoint, params=None, data=None, json=None, headers= except TypeError: headers = {"X-Nomad-Token": self.token} + if method == "post": + if json: + if self.vaulttoken: + if "Job" in json: + json["Job"]["VaultToken"] = self.vaulttoken + response = None try: diff --git a/start_daemons.sh b/start_daemons.sh new file mode 100755 index 0000000..3b547e0 --- /dev/null +++ b/start_daemons.sh @@ -0,0 +1,183 @@ +echo "Start daemons to test" + +if [ -z "${NOMAD_VERSION}" ]; then + echo "you should export NOMAD_VERSION" + exit 1 +fi + +if [ -z "${NOMAD_PORT_GUEST}" ]; then + NOMAD_PORT_GUEST="4646" +fi + +if [ -z "${NOMAD_IP}" ]; then + NOMAD_IP=127.0.0.1 +fi + +if [ -z "${VAULT_VERSION}" ]; then + VAULT_VERSION="0.6.2" +fi + +NOMAD_MAJOR_VERSION=`echo ${NOMAD_VERSION} | tr -d "."|sed "s/^0*//"` +VAULT_MAJOR_VERSION=`echo ${VAULT_VERSION} | tr -d "."|sed "s/^0*//"` + +if [ ${VAULT_MAJOR_VERSION} -lt 62 ]; then + echo "ATTENTION: Nomad Vault integration require Vault version >= 0.6.2. See https://www.nomadproject.io/guides/operations/vault-integration/index.html" +fi + +if [ ! -f /tmp/nomad ]; then + rm -rf /tmp/nomad +fi +echo "Nomad: Get Binary Files" +wget -q -P /tmp/ https://releases.hashicorp.com/nomad/${NOMAD_VERSION}/nomad_${NOMAD_VERSION}_linux_amd64.zip +yes | unzip -o -d /tmp /tmp/nomad_${NOMAD_VERSION}_linux_amd64.zip + + +if [ ! -f /tmp/vault ]; then + rm -rf /tmp/vault +fi +echo "Vault: Get Binary Files" +wget -q -P /tmp/ https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip +yes | unzip -o -d /tmp /tmp/vault_${VAULT_VERSION}_linux_amd64.zip + + +VAULT_ADDR="http://localhost:8200" + + +echo "Nomad: Create config folder" +rm -rf /tmp/nomad.d +mkdir -p /tmp/nomad.d + + +if [ ${VAULT_MAJOR_VERSION} -lt 62 ]; then + echo "Vault: this version is not supported" +else +echo "Vault: Create policy file" +cat << EOF > /tmp/policy-demo.hcl +path "secret/demo" { + capabilities = ["read"] +} +EOF + + echo "Vault: Start Daemon Version: ${VAULT_VERSION}" + /tmp/vault server -dev -dev-listen-address=0.0.0.0:8200 -dev-root-token-id="root" > /dev/null 2>&1 & + sleep 5 + + echo "Vault: Write Vault Policies with API" + # + # For version > 0.9.0 deprecated use of policies. Rules vs Policy + # + if [ ${VAULT_MAJOR_VERSION} -lt 90 ]; then + curl -s --data '{"rules":"path \"secret/demo\" {capabilities = [\"read\",\"list\"]}"}' --request PUT --header "X-Vault-Token: root" ${VAULT_ADDR}/v1/sys/policy/policy-demo + else + curl -s --data '{"policy":"path \"secret/data/demo\" {capabilities = [\"read\",\"list\"]}"}' --request PUT --header "X-Vault-Token: root" ${VAULT_ADDR}/v1/sys/policy/policy-demo + fi + + echo "Vault: Write Vault Secret" + # + # Vault version >= 0.9.0 require versioned secrets + # + if [ ${VAULT_MAJOR_VERSION} -lt 90 ]; then + curl -s --data '{"value":"python_nomad"}' --request PUT --header "X-Vault-Token: root" ${VAULT_ADDR}/v1/secret/demo + else + curl -s --data '{"options": {"cas": 0},"data": {"value": "python_nomad"}}' --request PUT --header "X-Vault-Token: root" ${VAULT_ADDR}/v1/secret/data/demo + fi + + +fi + + + + +if [ ${NOMAD_MAJOR_VERSION} -ge 50 ]; then +echo "Nomad: Enable Config Vault" +cat << EOF > /tmp/nomad.d/vault.hcl +vault +{ + enabled = true + address = "${VAULT_ADDR}" + token = "root" + allow_unauthenticated = false +} +EOF +fi + +echo "Nomad: Config base" +cat << EOF > /tmp/nomad.d/base_config.hcl +datacenter = "dc1" +name = "pynomad1" +bind_addr = "${NOMAD_IP}" +client +{ + enabled = true + node_class = "default" +} +ports +{ + http = ${NOMAD_PORT_GUEST} + rpc = 4647 +} +addresses +{ + http = "${NOMAD_IP}" + rpc = "${NOMAD_IP}" +} +advertise +{ + http = "${NOMAD_IP}:${NOMAD_PORT_GUEST}" + rpc = "${NOMAD_IP}:4647" +} +log_level = "INFO" +enable_debug = false +EOF + +echo "Nomad: Config Server" +cat << EOF > /tmp/nomad.d/server.hcl +server +{ + enabled = true + bootstrap_expect = 1 +} +EOF + +if [ ${NOMAD_MAJOR_VERSION} -gt 60 ]; then +echo "Nomad: Version $NOMAD_VERSION supports acls" +echo "Nomad: Config ACL" +cat << EOF > /tmp/nomad.d/acl.hcl +acl +{ + enabled = true + token_ttl = "30s" + policy_ttl = "60s" +} +EOF +else + echo "Nomad: version $NOMAD_VERSION" +fi + +echo "Nomad: Create test job samples" +rm -rf example.nomad +rm -rf example.json +/tmp/nomad init +/tmp/nomad run -output example.nomad > example.json +chmod 777 example* + +echo "Nomad: Starting Nomad" +nohup /tmp/nomad agent -server -dev -config=/tmp/nomad.d > /dev/null 2>&1 & + + +PID=`ps -eaf | grep "vault server -dev" | grep -v grep | awk '{print $2}'` +if [ "" != "$PID" ]; then + echo "Vault: service is Running" +else + echo "Vault: service is Stoped (could be not necessary)" +fi + +PID=`ps -eaf | grep "nomad agent -server" | grep -v grep | awk '{print $2}'` +if [ "" != "$PID" ]; then + echo "Nomad: service is Running" +else + echo "Nomad: service is Stoped. This make problems to make test!" +fi +sleep 10 + +echo "You can execute your test! ENJOY!" diff --git a/stop_daemons.sh b/stop_daemons.sh new file mode 100755 index 0000000..4152b5a --- /dev/null +++ b/stop_daemons.sh @@ -0,0 +1,17 @@ + + +echo "Vault: stoping" +PID=`ps -eaf | grep "vault server -dev" | grep -v grep | awk '{print $2}'` +if [ "" != "$PID" ]; then + echo "killing $PID" + kill -9 $PID +fi + +echo "Nomas: stoping" +PID=`ps -eaf | grep "nomad agent -server" | grep -v grep | awk '{print $2}'` +if [ "" != "$PID" ]; then + echo "killing $PID" + kill -9 $PID +fi + +rm -rf example.json example.nomad diff --git a/tests/common.py b/tests/common.py index e8de589..b253f9d 100644 --- a/tests/common.py +++ b/tests/common.py @@ -1,4 +1,5 @@ import os +import requests # internal ip of docker IP = os.environ.get("NOMAD_IP", "192.168.33.10") @@ -12,3 +13,21 @@ # Test namespace NOMAD_NAMESPACE = "admin" + +# Security token +VAULT_POLICY_INVALID_TOKEN = '1a77d23a-01f9-d848-8457-08bcec267c65' +VAULT_TOKEN = os.environ.get("VAULT_TOKEN", "root") +VAULT_ADDR = os.environ.get("VAULT_ADDR", "http://" + IP + ":8200") +VAULT_TEST = os.environ.get("VAULT_TEST", "true") +VAULT_VERSION = os.environ.get("VAULT_VERSION", "0.6.0") + +if VAULT_TEST != "false": + if tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) >= (0, 6, 2): + print ("\n Vault integration") + # create token based on policy "policy-demo" + headers = {'X-Vault-Token': 'root'} + payload = '{"policies": ["policy-demo"],"ttl": "3h","renewable": true}' + r = requests.post(VAULT_ADDR + "/v1" + "/auth/token/create", headers=headers, data=payload) + VAULT_POLICY_TOKEN=r.json()["auth"]["client_token"] + print("\n SecurityVaultAclForPolicy: {}\n".format(VAULT_POLICY_TOKEN)) + print("\n SecurityVaultRootToken: root") diff --git a/tests/conftest.py b/tests/conftest.py index a871f3b..aa8c27e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,3 +11,13 @@ def nomad_setup(): def nomad_setup_with_namespace(): n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, namespace=common.NOMAD_NAMESPACE) return n + +@pytest.fixture +def nomad_setup_vault_valid_token(): + n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, vaulttoken=common.VAULT_POLICY_TOKEN) + return n + +@pytest.fixture +def nomad_setup_vault_invalid_token(): + n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, vaulttoken=common.VAULT_POLICY_INVALID_TOKEN) + return n diff --git a/tests/test_acl.py b/tests/test_acl.py index ec7c151..ae84ddf 100644 --- a/tests/test_acl.py +++ b/tests/test_acl.py @@ -13,6 +13,9 @@ def test_create_bootstrap(nomad_setup): bootstrap = nomad_setup.acl.generate_bootstrap() assert "SecretID" in bootstrap common.NOMAD_TOKEN = bootstrap["SecretID"] + # For debug at vagrant you should use -s at test to view the token + # py.test -s --cov=nomad --cov-report=term-missing --runxfail tests/ + print("\n SecurityNomadRootToken: {}\n".format(common.NOMAD_TOKEN)) @pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") diff --git a/tests/test_integration_vault.py b/tests/test_integration_vault.py new file mode 100644 index 0000000..9d96ad2 --- /dev/null +++ b/tests/test_integration_vault.py @@ -0,0 +1,138 @@ +import pytest +import nomad +import json +import os +import requests +from requests.adapters import HTTPAdapter +from requests.packages.urllib3.util.retry import Retry +from nomad.api import exceptions + +def requests_retry_session(retries=3, backoff_factor=0.3, + status_forcelist=(500, 502, 504), session=None,): + session = session or requests.Session() + retry = Retry(total=retries, + read=retries, + connect=retries, + backoff_factor=backoff_factor, + status_forcelist=status_forcelist, + ) + adapter = HTTPAdapter(max_retries=retry) + session.mount('http://', adapter) + session.mount('https://', adapter) + return session + +# VAULT INTEGRATION +# Specific token for this policy +# Register Job +# Depens on version uses versioned secrets +# +# NOMAD v 0.8.5 --> vault: Fix a regression in which Nomad was only compatible with Vault versions greater than 0.10.0 [GH-4698] +# NOMAD v 0.5.6 --> server/vault: Fix Vault Client panic when given nonexistent role [GH-2648] +@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) < (0, 6, 2) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,8,5) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) <= (0,5,0) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,5,6) + or os.environ.get("VAULT_TEST") == "false", + reason="0.8.5 vault: Fix [GH-4698]. 0.5.6 server/vault: [GH-2648]. Review at https://github.com/hashicorp/nomad/blob/master/CHANGELOG.md") +def test_register_vault_job_valid(nomad_setup_vault_valid_token): + if tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) < (0, 9, 0): + vault_job = "vault.json" + else: + vault_job = "vault_kv.json" + with open(vault_job) as fh: + job = json.loads(fh.read()) + nomad_setup_vault_valid_token.job.register_job("vault", job) + assert "vault" in nomad_setup_vault_valid_token.job + + +# VAULT INTEGRATION +# Specific token for this policy +# Get Job +# Depens on version uses versioned secrets +# +# NOMAD v 0.8.5 --> vault: Fix a regression in which Nomad was only compatible with Vault versions greater than 0.10.0 [GH-4698] +# NOMAD v 0.5.6 --> server/vault: Fix Vault Client panic when given nonexistent role [GH-2648] +@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) < (0, 6, 2) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,8,5) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) <= (0,5,0) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,5,6) + or os.environ.get("VAULT_TEST") == "false", + reason="0.8.5 vault: Fix [GH-4698]. 0.5.6 server/vault: [GH-2648]. Review at https://github.com/hashicorp/nomad/blob/master/CHANGELOG.md") +def test_get_vault_job_valid(nomad_setup_vault_valid_token): + assert isinstance(nomad_setup_vault_valid_token.job.get_job("vault"), dict) == True + + +# VAULT INTEGRATION +# Specific token for this policy +# Validate Job +# Depens on version uses versioned secrets +# +# NOMAD v 0.8.5 --> vault: Fix a regression in which Nomad was only compatible with Vault versions greater than 0.10.0 [GH-4698] +# NOMAD v 0.5.6 --> server/vault: Fix Vault Client panic when given nonexistent role [GH-2648] +@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) < (0, 6, 2) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,8,5) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) <= (0,5,0) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,5,6) + or os.environ.get("VAULT_TEST") == "false", + reason="0.8.5 vault: Fix [GH-4698]. 0.5.6 server/vault: [GH-2648]. Review at https://github.com/hashicorp/nomad/blob/master/CHANGELOG.md") +def test_get_vault_job_valid(nomad_setup_vault_valid_token): + assert isinstance(nomad_setup_vault_valid_token.job.get_job("vault"), dict) == True + +# VAULT INTEGRATION +# Specific token for this policy +# Validate secret from vault +# Depens on version uses versioned secrets +# +# NOMAD v 0.8.5 --> vault: Fix a regression in which Nomad was only compatible with Vault versions greater than 0.10.0 [GH-4698] +# NOMAD v 0.5.6 --> server/vault: Fix Vault Client panic when given nonexistent role [GH-2648] +@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) < (0, 6, 2) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,8,5) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) <= (0,5,0) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,5,6) + or os.environ.get("VAULT_TEST") == "false", + reason="0.8.5 vault: Fix [GH-4698]. 0.5.6 server/vault: [GH-2648]. Review at https://github.com/hashicorp/nomad/blob/master/CHANGELOG.md") +def test_get_secret_from_vault_job_valid(): + url="http://localhost:8080" + response = requests_retry_session(retries=20).get(url,timeout=60) + assert "python_nomad" in response.text + + +# VAULT INTEGRATION +# Specific token for this policy +# De-Register Job +# Depens on version uses versioned secrets +# +# NOMAD v 0.8.5 --> vault: Fix a regression in which Nomad was only compatible with Vault versions greater than 0.10.0 [GH-4698] +# NOMAD v 0.5.6 --> server/vault: Fix Vault Client panic when given nonexistent role [GH-2648] +@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) < (0, 6, 2) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,8,5) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) <= (0,5,0) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,5,6) + or os.environ.get("VAULT_TEST") == "false", + reason="0.8.5 vault: Fix [GH-4698]. 0.5.6 server/vault: [GH-2648]. Review at https://github.com/hashicorp/nomad/blob/master/CHANGELOG.md") +def test_delete_vault_job(nomad_setup_vault_valid_token): + assert "EvalID" in nomad_setup_vault_valid_token.job.deregister_job("vault") + test_register_vault_job_valid(nomad_setup_vault_valid_token) + +# VAULT INTEGRATION +# Specific token for this policy +# Register Job with Bad Vault Token. It will report not authorized +# Depens on version uses versioned secrets +# +# NOMAD v 0.8.5 --> vault: Fix a regression in which Nomad was only compatible with Vault versions greater than 0.10.0 [GH-4698] +# NOMAD v 0.5.6 --> server/vault: Fix Vault Client panic when given nonexistent role [GH-2648] +@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) < (0, 6, 2) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,8,5) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) <= (0,5,0) + or tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) == (0,5,6) + or os.environ.get("VAULT_TEST") == "false", + reason="0.8.5 vault: Fix [GH-4698]. 0.5.6 server/vault: [GH-2648]. Review at https://github.com/hashicorp/nomad/blob/master/CHANGELOG.md") +def test_register_vault_job_invalid(nomad_setup_vault_invalid_token): + if tuple(int(i) for i in os.environ.get("VAULT_VERSION").split(".")) < (0, 9, 0): + vault_job = "vault.json" + else: + vault_job = "vault_kv.json" + with open(vault_job) as fh: + job = json.loads(fh.read()) + with pytest.raises(nomad.api.exceptions.BaseNomadException): + nomad_setup_vault_invalid_token.job.register_job("vault", job) diff --git a/vault.hcl b/vault.hcl new file mode 100644 index 0000000..626d221 --- /dev/null +++ b/vault.hcl @@ -0,0 +1,38 @@ +job "vault" { + datacenters = ["dc1"] + type = "service" + vault { policies = ["policy-demo"]} + group "web" { + count = 1 + restart { + attempts = 2 + interval = "1m" + delay = "15s" + mode = "fail" + } + task "vatul-sercret" { + driver = "docker" + config { + image = "i4spserrano/nomadvaultsecret:latest" + port_map { + http = 8080 + } + } + template { + data = < server/vault: Fix Vault Client panic when given nonexistent role [GH-2648] +- NOMAD v 0.8.5 --> vault: Fix a regression in which Nomad was only compatible with Vault versions greater than 0.10.0 [GH-4698] +- NOMAD (all version) vs Vault 0.11.0 --> Make crash nomad agent.