Skip to content
This repository was archived by the owner on Jan 8, 2024. It is now read-only.

Feat/nomad consul vault tokens #3222

Merged
merged 7 commits into from
Apr 18, 2022
Merged

Conversation

paladin-devops
Copy link
Contributor

Add support for authenticating to Consul & Vault when registering Nomad job for both Nomad deployers. Consul token should be supplied via the CONSUL_HTTP_TOKEN env var, and Vault token via the VAULT_TOKEN env var of the runner.

Relevant Nomad API code:
https://github.com/hashicorp/nomad/blob/8f7abae89fb6aef25161a90457e42a1a3cc07fa5/api/jobs.go#L843-L844

Addresses #3206

@paladin-devops
Copy link
Contributor Author

Working as expected, I used the nomad-jobspec example from the waypoint-examples repo to test this out, but added a service and vault stanza to trigger the Consul/Vault integrations. Also, my Nomad config file runs with the allow_unauthenticated configs set to false for Consul and Vault:

consul {
  address = "127.0.0.1:8500"
  allow_unauthenticated = false
  token = "my-token"
}

vault {
  enabled = true
  address = "http://127.0.0.1:8200"
  allow_unauthenticated = false
  token = "my-token"
}

Consul

Below shows before/after running deploy with CONSUL_HTTP_TOKEN specified in the runner config.

% waypoint config get -runner                                                                     
  SCOPE | NAME | VALUE | WORKSPACE | LABELS  
--------+------+-------+-----------+---------

% waypoint deploy                

» Deploying example-nodejs...
  Performing operation locally
✓ Running deploy v8
✓ Deleting job: 
! 2 errors occurred:
  	* Unexpected response code: 500 (job-submitter consul token denied: missing
  consul token)
  	* Error during rollback: Unexpected response code: 500 (missing job ID for
  deregistering)
  
  
% waypoint config set -runner -scope=global CONSUL_HTTP_TOKEN=my-token

% waypoint config get -runner                                        
  SCOPE  |       NAME        |                VALUE                 | WORKSPACE | LABELS  
---------+-------------------+--------------------------------------+-----------+---------
  global | CONSUL_HTTP_TOKEN | my-token |           |         
% waypoint deploy                       

» Deploying example-nodejs...
  Performing operation locally
✓ Running deploy v9
✓ Job registration successful
✓ Allocation "ALLOC_ID" created: node "NODE_ID", group "app"
✓ Evaluation status changed: "pending" -> "complete"
✓ Evaluation "EVAL_ID" finished with status "complete"
✓ Deployment successfully rolled out!

  Performing operation locally
✓ Finished building report for Nomad platform
✓ Getting job info...
✓ Job "web" is reporting ready!

Vault

Below shows before/after running deploy with VAULT_TOKEN specified in the runner config.

% waypoint deploy -release=false

» Deploying example-nodejs...
  Performing operation locally
✓ Running deploy v10
✓ Deleting job: 
! 2 errors occurred:
  	* Unexpected response code: 500 (Vault policies requested but missing Vault
  Token)
  	* Error during rollback: Unexpected response code: 500 (missing job ID for
  deregistering)
  
  
% waypoint config set -runner -scope=global VAULT_TOKEN=my-token              

% waypoint deploy                      

» Deploying example-nodejs...
  Performing operation locally
✓ Running deploy v11
✓ Job registration successful
✓ Allocation "ALLOC_ID" created: node "NODE_ID", group "app"
✓ Evaluation status changed: "pending" -> "complete"
✓ Evaluation "EVAL_ID" finished with status "complete"
✓ Deployment successfully rolled out!

@briancain briancain requested a review from a team April 14, 2022 20:39
Copy link
Member

@briancain briancain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, a fairly straightforward change! 🎉

I'm curious, how can we let users of the Nomad plugin know how to use this in both a local and remote runner context? 🤔 I imagine we should document that Waypoint will respect these env vars, but it might not be obvious that they'd need to configure runners with the env var for remote runs.

}

func VaultAuth() (string, error) {
return os.Getenv("VAULT_TOKEN"), nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to confirm this works with remote runners if you haven't already given that a shot with this PR. I think you'd have to do a waypoint config set -runner CONSUL_HTTP_TOKEN=abcd VAULT_TOKEN=1234 and then try an Up operation with ODR/Remote runners and see that the deployment succeeded with these values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@briancain Looking good! I first unset the tokens to verify that it would fail without them w/remote-operations:

% waypoint config set -scope=global -runner VAULT_TOKEN=                        

% waypoint config set -scope=global -runner CONSUL_HTTP_TOKEN=

% waypoint deploy -p=example-nodejs -local=false -release=false

» Deploying example-nodejs...
  Performing this operation on a remote runner with id "JOB_ID"

» Cloning data from Git
  URL: https://github.com/hashicorp/waypoint-examples
  Ref: feat/nomad-consul-vault-integration
✓ Running deploy v14
✓ Deleting job: 
! 2 errors occurred:
  	* Unexpected response code: 500 (Vault policies requested but missing Vault
  Token)
  	* Error during rollback: Unexpected response code: 500 (missing job ID for
  deregistering)

After setting them again, the job deployed:

% waypoint config set -scope=global -runner CONSUL_HTTP_TOKEN=my-token

% waypoint config set -scope=global -runner VAULT_TOKEN=my-token

% waypoint deploy -p=example-nodejs -local=false -release=false                                   

» Deploying example-nodejs...
  Performing this operation on a remote runner with id "JOB_ID"

» Cloning data from Git
  URL: https://github.com/hashicorp/waypoint-examples
  Ref: feat/nomad-consul-vault-integration
✓ Job registration successful
✓ Allocation "ALLOC_ID" created: node "NODE_ID", group "app"
✓ Evaluation status changed: "pending" -> "complete"
✓ Evaluation "EVAL_ID" finished with status "complete"
✓ Deployment successfully rolled out!
✓ Running deploy v15

  Performing this operation on a remote runner with id "JOB_ID"

» Cloning data from Git
  URL: https://github.com/hashicorp/waypoint-examples
  Ref: feat/nomad-consul-vault-integration
✓ Finished building report for Nomad platform
✓ Getting job info...
✓ Job "web" is reporting ready!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 🎉 Looks great

@briancain
Copy link
Member

Actually, in the topic of where to document this, I think each plugin has a top level Doc that can be defined. It might also have an Env var field?

func (p *Platform) Documentation() (*docs.Documentation, error) {

@@ -211,6 +211,18 @@ func (p *Platform) resourceJobCreate(
job.TaskGroups[0].Tasks[0].Config = config
job.TaskGroups[0].Tasks[0].Env = env

// Get Consul ACL token from environment
*job.ConsulToken, err = ConsulAuth()
Copy link
Contributor

@xiaolin-ninja xiaolin-ninja Apr 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Soooo I spent a while trying to wrap my head around this, for other reviewers: this is assigned to pointer job because ConsulToken is a pointer string.

Copy link
Contributor

@xiaolin-ninja xiaolin-ninja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good!

Copy link
Member

@briancain briancain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me @paladin-devops ! You might need to generate the website docs, but otherwise looking gooood 👍🏻

}

func VaultAuth() (string, error) {
return os.Getenv("VAULT_TOKEN"), nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 🎉 Looks great

"vault_token",
"The Vault token used to deploy the Nomad job with a token having specific Vault policies attached.",
docs.Summary("Uses the runner config environment variable VAULT_TOKEN."),
docs.EnvVar("VAULT_TOKEN"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Awesome, thank you. These env var fields are exactly what I was thinking. Looks gooood 👍🏻

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might need to run a `make gen/website-mdx. I think this will generate the website docs based on these fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@briancain done!

Copy link
Member

@briancain briancain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants