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

consul: include admin partition in JWT login requests #22226

Merged
merged 1 commit into from
May 29, 2024

Conversation

tgross
Copy link
Member

@tgross tgross commented May 23, 2024

When logging into a JWT auth method, we need to explicitly supply the Consul admin partition if the local Consul agent is in a partition. We can't derive this from agent configuration because the Consul agent's configuration is canonical, so instead we get the partition from the fingerprint (if available). This changeset updates the Consul client constructor so that we close over the partition from the fingerprint.

Ref: https://hashicorp.atlassian.net/browse/NET-9451

@tgross
Copy link
Member Author

tgross commented May 23, 2024

Our unit tests can't really exercise this area of code well, but the E2E tests here exercise this code for Consul CE and make sure we don't break the use case where no partition has been set. I've successfully end-to-end tested this with Consul Enterprise with the following setup.

Nomad server agent Consul config
consul {
  token                 = "redacted"
  allow_unauthenticated = true

  service_identity {
    aud = ["consul.io"]
    ttl = "1h"
  }

  task_identity {
    aud = ["consul.io"]
    ttl = "1h"
  }
}
Nomad client agent Consul config
consul {
  token                 = "redacted"
  allow_unauthenticated = true
}
setup

auth config file

{
  "JWKSURL": "http://10.37.105.3:4646/.well-known/jwks.json",
  "JWTSupportedAlgs": ["RS256"],
  "BoundAudiences": ["consul.io"],
  "ClaimMappings": {
    "consul_namespace": "consul_namespace",
    "nomad_namespace": "nomad_namespace",
    "nomad_job_id": "nomad_job_id",
    "nomad_task": "nomad_task",
    "nomad_service": "nomad_service"
  }
}

task policy file

key_prefix "nomad/" {
  policy = "read"
}

service_prefix "" {
  policy = "read"
}

setup script

#!/usr/bin/env bash

set -e

consul partition create -name dev
nomad namespace apply foo
consul namespace create -partition dev -name foo

# create the auth method in the dev partition
consul acl auth-method create \
  -name 'nomad-workloads' \
  -type jwt \
  -partition dev \
  -description 'login method for Nomad workloads' \
  -format json \
  -namespace-rule-selector='' \
  -namespace-rule-bind-namespace='${value.nomad_namespace}' \
  -config "@consul-auth-method-config.json"

# create the task (templates) policy in the partition and namespace
consul acl policy create \
       -partition dev \
       -namespace foo \
       -name workloads-policy-dev \
       -rules "@consul-task-policy.hcl"

# create the role for tasks (templates) in the partition and namespace
consul acl role create \
       -name "nomad-tasks-foo" \
       -namespace foo \
       -partition dev \
       -description "role for Nomad workloads in foo namespace" \
       -policy-name "workloads-policy-dev"

# create the binding rule for tasks (templates)
consul acl binding-rule create \
         -method 'nomad-workloads' \
         -partition dev \
         -description 'binding rule for Nomad template workload identities (WI)' \
         -bind-type role \
         -bind-name 'nomad-tasks-${value.nomad_namespace}' \
         -selector '"nomad_service" not in value'

# create the binding rule for services
consul acl binding-rule create \
         -method 'nomad-workloads' \
         -partition dev \
         -description 'binding rule for Nomad workload identities (WI)' \
         -bind-type service \
         -bind-name '${value.nomad_service}' \
         -selector '"nomad_service" in value'

My test job requires both a service login and a task login.

jobspec
job "example" {

  group "web" {

    network {
      mode = "bridge"
      port "www" {
        to = 8001
      }
    }

    service {
      port = "www"
    }

    task "http" {

      driver = "docker"

      config {
        image   = "busybox:1"
        command = "httpd"
        args    = ["-vv", "-f", "-p", "8001", "-h", "/local"]
        ports   = ["www"]
      }

      identity {
        env  = true
        file = true
      }

      template {
        data        = "<html>hello, world</html>"
        destination = "local/index.html"
      }

      resources {
        cpu    = 100
        memory = 100
      }

    }
  }
}

@tgross tgross marked this pull request as ready for review May 23, 2024 16:42
@tgross tgross added the backport/ent/1.7.x+ent Changes are backported to 1.7.x+ent label May 23, 2024
When logging into a JWT auth method, we need to explicitly supply the Consul
admin partition if the local Consul agent is in a partition. We can't derive
this from agent configuration because the Consul agent's configuration is
canonical, so instead we get the partition from the fingerprint (if
available). This changeset updates the Consul client constructor so that we
close over the partition from the fingerprint.

Ref: https://hashicorp.atlassian.net/browse/NET-9451
@tgross tgross force-pushed the consul-partition-for-client branch from 583cc41 to 6f68109 Compare May 23, 2024 16:44
@tgross tgross added the backport/ent/1.8.x+ent Changes are backported to 1.8.x+ent label May 23, 2024
@tgross tgross requested a review from gulducat May 23, 2024 18:15
Copy link
Contributor

@pkazmierczak pkazmierczak left a comment

Choose a reason for hiding this comment

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

LGTM!

return nil, fmt.Errorf("nil consul config")
}
// ConsulClientFunc creates a new Consul client for the specific Consul config
type ConsulClientFunc func(config *config.ConsulConfig, logger hclog.Logger) (Client, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

that's a nice refactoring 👌

@tgross tgross added this to the 1.8.1 milestone May 28, 2024
@tgross tgross merged commit 1407472 into main May 29, 2024
22 checks passed
@tgross tgross deleted the consul-partition-for-client branch May 29, 2024 20:31
@tgross tgross added the backport/1.8.x backport to 1.8.x release line label May 29, 2024
Copy link

github-actions bot commented Jan 6, 2025

I'm going to lock this pull request because it has been closed for 120 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 6, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
backport/ent/1.7.x+ent Changes are backported to 1.7.x+ent backport/ent/1.8.x+ent Changes are backported to 1.8.x+ent backport/1.8.x backport to 1.8.x release line theme/consul theme/enterprise Issues related to Enterprise features theme/workload-identity type/bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants