Merge "Support custom claim and print meta info in zuul-admin create-auth-token"

This commit is contained in:
Zuul
2025-03-26 10:59:41 +00:00
committed by Gerrit Code Review
3 changed files with 55 additions and 7 deletions

View File

@@ -45,14 +45,22 @@ create-auth-token
Example::
zuul-admin create-auth-token --auth-config zuul-operator --user alice --tenant tenantA --expires-in 1800
zuul-admin create-auth-token --auth-config zuul-operator --user alice --tenant tenantA --expires-in 1800 --print-meta-info
The return value is the value of the ``Authorization`` header the user must set
when querying a protected endpoint on Zuul's REST API.
when querying a protected endpoint on Zuul's REST API. The meta information of
the token will be printed when "--print-meta-info" is specified.
Example::
bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbWFuYWdlc2Yuc2ZyZG90ZXN0aW5zdGFuY2Uub3JnIiwienV1bC50ZW5hbnRzIjp7ImxvY2FsIjoiKiJ9LCJleHAiOjE1Mzc0MTcxOTguMzc3NTQ0fQ.DLbKx1J84wV4Vm7sv3zw9Bw9-WuIka7WkPQxGDAHz7s
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NDEzNTAzMTksImV4cCI6MTc0MTM1MjExOSwiaXNzIjoienV1bF9vcGVyYXRvciIsImF1ZCI6Inp1dWwuZXhhbXBsZS5jb20iLCJzdWIiOiJhbGljZSIsInp1dWwiOnsiYWRtaW4iOlsidGVuYW50QSJdfX0.cW3U5LEFJS0TM-EDELZS9_hhbxdw-xObLwvDQKL55fM
---------------- Meta Info ----------------
Tenant: tenantA
User: alice
Generated At: 2025-03-07 12:25:19 UTC
Expired At: 2025-03-07 12:55:19 UTC
SHA1 Checksum: f52018044a209ce7eed5e587c41cc8b360af891d
-------------------------------------------
.. _export-keys:

View File

@@ -153,14 +153,17 @@ class TestWebTokenClient(BaseClientTestCase):
'create-auth-token',
'--auth-conf', 'zuul_operator',
'--user', 'marshmallow_man',
'--tenant', 'tenant_one', ],
'--tenant', 'tenant_one',
'--claim', 'claim1:value1',
'--claim', 'claim2:value2',
'--print-meta-info', ],
stdout=subprocess.PIPE)
now = time.time()
out, _ = p.communicate()
self.assertEqual(p.returncode, 0, 'The command must exit 0')
self.assertTrue(out.startswith(b"Bearer "), out)
# there is a trailing carriage return in the output
token = jwt.decode(out[len("Bearer "):-1],
# Get the token from the first line of the output
token = jwt.decode(out.split(b'\n')[0][len("Bearer "):],
key=self.config.get(
'auth zuul_operator',
'secret'),
@@ -173,12 +176,18 @@ class TestWebTokenClient(BaseClientTestCase):
self.assertEqual('marshmallow_man', token.get('sub'))
self.assertEqual('zuul_operator', token.get('iss'))
self.assertEqual('zuul.example.com', token.get('aud'))
self.assertEqual('value1', token.get('claim1'))
self.assertEqual('value2', token.get('claim2'))
admin_tenants = token.get('zuul', {}).get('admin', [])
self.assertTrue('tenant_one' in admin_tenants, admin_tenants)
# allow one minute for the process to run
self.assertTrue(580 <= int(token['exp']) - now < 660,
(token['exp'], now))
# Get the meta info from the second line of the output
meta_info_header = out.split(b'\n')[1]
self.assertIn("Meta Info", meta_info_header.decode('utf-8'))
class TestKeyOperations(ZuulTestCase):
tenant_config_file = 'config/single-tenant/main.yaml'

View File

@@ -19,6 +19,7 @@ import babel.dates
import datetime
import dateutil.parser
import dateutil.tz
import hashlib
import json
import jwt
import logging
@@ -402,6 +403,18 @@ class Client(zuul.cmd.ZuulApp):
type=int,
default=600,
required=False)
cmd_create_auth_token.add_argument(
'--claim',
help=('Custom claim in format claim:value. It can '
'be used multiple times to add multiple claims.'),
action="extend",
type=lambda x: tuple(x.split(':')),
nargs='*',
default=[])
cmd_create_auth_token.add_argument(
'--print-meta-info',
action='store_true',
help="When specified, the meta info of the token will be printed")
cmd_create_auth_token.set_defaults(func=self.create_auth_token)
# Key storage
@@ -740,13 +753,20 @@ class Client(zuul.cmd.ZuulApp):
% self.args.auth_config)
sys.exit(1)
now = int(time.time())
exp = now + self.args.expires_in
token = {'iat': now,
'exp': now + self.args.expires_in,
'exp': exp,
'iss': get_default(self.config, auth_section, 'issuer_id'),
'aud': get_default(self.config, auth_section, 'client_id'),
'sub': self.args.user,
'zuul': {'admin': [self.args.tenant, ]},
}
# Add custom claims, allow to overwrite default claims
# when it is required.
for k, v in self.args.claim:
token[k] = v
driver = get_default(
self.config, auth_section, 'driver')
if driver == 'HS256':
@@ -768,6 +788,17 @@ class Client(zuul.cmd.ZuulApp):
key=key,
algorithm=driver)
print("Bearer %s" % auth_token)
if self.args.print_meta_info:
print("---------------- Meta Info ----------------")
print("Tenant:\t\t%s" % self.args.tenant)
print("User:\t\t%s" % self.args.user)
print("Generated At:\t%s" % time.strftime(
"%Y-%m-%d %H:%M:%S UTC", time.gmtime(now)))
print("Expired At:\t%s" % time.strftime(
"%Y-%m-%d %H:%M:%S UTC", time.gmtime(exp)))
print("SHA1 Checksum:\t%s" % hashlib.sha1(
auth_token.encode("utf-8")).hexdigest())
print("-------------------------------------------")
err_code = 0
except Exception as e:
print("Error when generating Auth Token")