Skip to content

Commit

Permalink
gRPC authentication proposal - using gRPC secure channels
Browse files Browse the repository at this point in the history
  • Loading branch information
jacbar01-arm committed Nov 12, 2024
1 parent 0304ec6 commit 7a2b399
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 11 deletions.
2 changes: 2 additions & 0 deletions labgrid/remote/authentication/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
__pycache__/*
7 changes: 7 additions & 0 deletions labgrid/remote/authentication/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
__all__ = ['SERVER_CERTIFICATE', 'SERVER_CERTIFICATE_KEY',
'generate_jwt_token', 'is_token_valid', 'CustomAuthMetadataPlugin',
'SignatureValidationInterceptor']

from .helper_functions import SERVER_CERTIFICATE, SERVER_CERTIFICATE_KEY
from .helper_functions import generate_jwt_token, is_token_valid
from .plugins_interceptors import CustomAuthMetadataPlugin, SignatureValidationInterceptor
74 changes: 74 additions & 0 deletions labgrid/remote/authentication/helper_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import datetime
import os
import jwt


def load_credential_from_file(filepath):
'''
Loads certificate from file and returns it as bytes
Args:
filepath (str): The path to the file to load
Returns:
The content of the certificate file as bytes
'''
real_path = os.path.join(os.path.dirname(__file__), filepath)
with open(real_path, "rb") as f:
return f.read()


token_secret = '3#pn$%agj02_r119*peydh&w+kt(2gy=n&e-68t19fup#33=)7'

# sample token details
jwt_token_details = {
'id': 'labgrid',
'username': 'labgrid-username',
'firstName': 'firstName',
'lastName': 'lastName',
'email': '[email protected]',
'isStaff': True,
'exp': (datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=1)),}


def generate_jwt_token(token_details=jwt_token_details, secret=token_secret):
'''
Generates a JWT token with the given token details and secret and return it
'''
return jwt.encode(token_details, secret, algorithm='HS256')


def is_token_valid(token, secret_key=token_secret):
'''
Validates the given token using the secret key and returns True if the token is valid
Args:
token (str): The token to validate
secret_key (str): The secret key to use for validation
Returns:
True if the token is valid, False otherwise
'''
try:
decoded_token =jwt.decode(token, secret_key, algorithms=['HS256'])
except jwt.ExpiredSignatureError:
return False
except jwt.InvalidTokenError:
return False

if not 'id' in decoded_token:
return False

if not 'exp' in decoded_token:
return False

exp_date = datetime.datetime.fromtimestamp(decoded_token['exp'])
curr_date = datetime.datetime.utcnow()

if exp_date < curr_date:
return False

return True

SERVER_CERTIFICATE=load_credential_from_file('../Certificates/server.crt')
SERVER_CERTIFICATE_KEY=load_credential_from_file('../Certificates/server.key')
42 changes: 42 additions & 0 deletions labgrid/remote/authentication/plugins_interceptors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import grpc
from .helper_functions import generate_jwt_token, is_token_valid


JWT_TOKEN = generate_jwt_token()

class CustomAuthMetadataPlugin(grpc.AuthMetadataPlugin):
'''
Authentication plugin used to add {'x-signature', JWT_TOKEN} HTTP header
'''
def __call__(self, context, callback):
signature = context.method_name[::-1]
signature = JWT_TOKEN
callback((("x-signature", signature),), None)


class SignatureValidationInterceptor(grpc.aio.ServerInterceptor):
'''
Middleware used to validate the JWT token in the HTTP header
'''
def __init__(self):
def abort(ignored_request, context):
context.abort(grpc.StatusCode.UNAUTHENTICATED, "Invalid signature")
self._abort_handler = grpc.unary_unary_rpc_method_handler(abort)

def intercept_service(self, continuation, handler_call_details):
'''
Extracts the token from the HTTP header and validates it
'''
token = ''

for item in handler_call_details.invocation_metadata:
dictionary = item._asdict()
if dictionary['key'] == 'x-signature':
token = dictionary['value']
break

if token != '':
if is_token_valid(token):
return continuation(handler_call_details)

self._abort_handler()
33 changes: 33 additions & 0 deletions labgrid/remote/certificates/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFrDCCA5SgAwIBAgIUF/RY4CD6al79N6+WEl0OLmRuv5YwDQYJKoZIhvcNAQEL
BQAwfDELMAkGA1UEBhMCR0IxEzARBgNVBAcMCk1hbmNoZXN0ZXIxFDASBgNVBAoM
C0FSTSBMaW1pdGVkMQ8wDQYDVQQLDAZDRS1HUFUxEjAQBgNVBAMMCWxvY2FsaG9z
dDEdMBsGCSqGSIb3DQEJARYOY2UtZ3B1QGFybS5jb20wHhcNMjQxMDI2MTE0NDQ5
WhcNMjUxMDI2MTE0NDQ5WjB8MQswCQYDVQQGEwJHQjETMBEGA1UEBwwKTWFuY2hl
c3RlcjEUMBIGA1UECgwLQVJNIExpbWl0ZWQxDzANBgNVBAsMBkNFLUdQVTESMBAG
A1UEAwwJbG9jYWxob3N0MR0wGwYJKoZIhvcNAQkBFg5jZS1ncHVAYXJtLmNvbTCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOc3FStpCnjB5DdZW4wMZFX8
l6TetEo02QSonD0JCoyMIvc1oUUDR1EZdPDNIEsNUA//V5o6I4zENbPz9vRyvXzZ
/Qn6q55CLwPwFfnOkjD6SHDcS4KTjAVYhPSZxak5pqCJoERkvJFfUeSwR5ksYBhE
rvniiP9brmL9jiNywysPcFwOEC6Sidku6zYoNz0L+++JWBbMoFwfLvQPoQcdqidY
3ULLX7VsPE0MzkXsNjiKo68XiqqNjExld111hfq1hZxpfQr5xdYw21djK/ELEKYY
EP0VlCdRysCvO1RE/FrNlTPlJkTW/suTaDq8Y77peDmBkyfvCGfHraCkIalUDFTs
n7SQURUuVdTQK5D1Wrdym7ux1eAUcLVLjBTaKbug3dTh1bFnIJySUERaGfxo7b+Q
7HEzc00wsrPbTTCnJIgZUDmD+f8BFxcyOscQZr9z3Jz+zTi1kAVTrkzDAsl/I41l
OjmnP8ICDUL8A1WB7z/moJjUrX7DpkPyLHMQbbuqGXEzUMdK2Rs54a69FYwGT3NR
xaVjREsqawxfpnvsbsRzcJYTZ7jmhJkAUd2mZ8eryAmuyReKFXbBAT/nef5gVMWK
zSVix6Bnxm0QHVlooCy3IjygQdpTgYXpcYBB0h2CQcfkD1PjhLggh3ckCvWBzuwH
x/vrDPGRc5jgqAVKtIGdAgMBAAGjJjAkMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYD
VR0PAQH/BAQDAgHGMA0GCSqGSIb3DQEBCwUAA4ICAQDkF/w4X/D3zWfpBCEKWWdh
s30cUYZLO7xUr+yXb/M3ZVXSLZ2FaM9OeE3DA1oE21N9khBkw6XpqN9YTENrYyue
ycUbDnkUiHMHM2k5zc3SIqpMIza3UasjS+zMuMHP/mEaummF8Ou8JLyaEMLIIg/I
ry+trqV8Z/10w5o2J3JcrlOaA2CF25QF+HGgYFSYuVpwO/Gp8lHnNTh8TJjXxmve
f4Jt2DzWr1pkvnTYPNlOz+2HIP+SxZs+k4kQ0wwQOAVcJAlhLLiTbwK47IeV8BHR
ALMzvW3Ahjh6WZhnr86oU7Sm0GAQOT+lCqholRi6RbcXnCux2BST/oiwDe1ajmE2
EZjq+l4A6CVp0CUfA/pBl+0oPNZWjnvDQeY1mI5bK2o/54IsOFNRl5SBIpBvMtqM
EZTKwM958UyQqOrWUCwBNFJ+jcYR+coKKmbGiYYRCkT4fIjLauzJGnJ+Ni9cA9ty
zBGow461rUeoMDCzIlBrXNbIZoLkmXT1/2+UXWZmLmgK5wSoOFug0CEpSgr3dzlP
4bhMzyxcxEe1in8haFRv35y10dhVTNJ7M/Oxo+r2EqrS9aDkzADIsUta1Huz/V0Z
93rFBhRZBbCeEtZ+G0i3XOsSAPueyf6EJplI+Hpd9Nw/hNjbdbxk8c5WgUR3oT8q
5pZY1waC7qPyPeEyDyribA==
-----END CERTIFICATE-----
31 changes: 31 additions & 0 deletions labgrid/remote/certificates/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFbDCCA1QCAQEwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCR0IxEzARBgNV
BAcMCk1hbmNoZXN0ZXIxFDASBgNVBAoMC0FSTSBMaW1pdGVkMQ8wDQYDVQQLDAZD
RS1HUFUxEjAQBgNVBAMMCWxvY2FsaG9zdDEdMBsGCSqGSIb3DQEJARYOY2UtZ3B1
QGFybS5jb20wHhcNMjQxMDI2MTIwNzQ3WhcNMjUxMDI2MTIwNzQ3WjB8MQswCQYD
VQQGEwJHQjETMBEGA1UEBwwKTWFuY2hlc3RlcjEUMBIGA1UECgwLQVJNIExpbWl0
ZWQxDzANBgNVBAsMBkNFLUdQVTESMBAGA1UEAwwJbG9jYWxob3N0MR0wGwYJKoZI
hvcNAQkBFg5jZS1ncHVAYXJtLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
AgoCggIBAKjd3ctmc6iF31b3fvyNbOKb5LBeeDrspbDYqIPUncDxjfP0Krwd1VKu
7dKQoA5t5WR1gasJRcfvs/T3oRAuYUuZTU2HOeXmYwzhW4g5qnNuZt0M7B6C2j4C
leDRBpp6mwORmACS/ldXpxLkHzAjgb5aI5EdCBhc63mSQd4DlZR0TtVVNGM0In6O
D8kvCD21XW8LvxFKCzVPyOlkY2KOMfhZg7g21Vjql8ZBPZCkW067hS8o12IUyJC/
/WZUWFV0sDhHFEurgwa/RzUg8snwhiGQ+Q6BNTdvZg26X4Sj8Fu31LUz9Wx2Hc7T
qtsmNoDhGY6iPu7T8DnLeGxzsbBAF28IjTx1lHRTwhw/nhv5e0LQ5/CE9F3u6YsO
Ywvj5xm0prlVxdg+uvmsWKJdATIKz1ko5rG1beEO8GCb9FaZ4spBNRC4X90fPwCN
YxSeA4Im+lPmnMPGe/mtzjVDTPRrpoJUdd90ELkof7jVyWj4XBnmFh15l0+1liP1
Ey9P0zm6HuoZNirGHbJryPyqbmF4pFA3t+5psvpy5Oh19O2SzA935LfLH+bZKkd4
6Q7iOz15dbBA1bJfbT9ElozCvaGTNLg9ElXtgb2mAQ0ozTt7Y7WtRiHmKUSo5OBn
h5X9yBhFgkmFeSaJAtFWsnFfqrmgL9JOVQckt0HzhBbZ7f+5nPJLAgMBAAEwDQYJ
KoZIhvcNAQELBQADggIBALnmgUmEquYdgwMlZycw2Kxjg6XaWt9Ere7ngBs8KVYV
md6wbC6vLQxcpVxlX4Xv8rtyF+F+A1vK6E0TQCjLKiwBhZpZmhYK4Wopq/4Z/jOI
o+GiPa9J4KTJtQNmoiJcwElaN3AOfPqPh7tCnepMJWSHoFmmHsRjyo8SxPmblQv1
XJ4L/Wr3dTt2QEItW8IE3TGblBWRuZGpDu/6KIL5li/jC3a+VPLAEQBWZgfDzENV
S0SstPBVGzwjcLXdhw2Okz36sghMVTe0C3kjUamrxmgKBj9y6pmGDsr8vNECCWCL
uKjuUw7KMYORLOSOabbRS+XhjfxzCQUxu0yn+RneykkNipxMHqBJSCM5XBi83iHG
fxr5jYAdYyp7HBvJ/l2iFGYaS5/O/AVmraGsEMzWgGZBG+x9XBQo6CDZbGjjNXUe
bTVB3aVk1tIyeK5rWaJOhZq4YzAvysd0cTR0lLr9dKQuYf0aPDITL0qKbk7JQTrN
yq+dOZ4ipnjiaLI/Fv09TZN/Rin6Hqx9p+41lQQy8cGa2FYLGMvBrthKkOUfTrl9
hVkujbNSXL09cwWuUgV6KLNXNXX02lp2LG3R+b5BWoNHKZYabAInVfv5M3Z40yec
KgMa4bOE6NAxg5F5DqjGWuwWdKG1hIV6CLqVUzhDP7rrg4LnnpELr0ms56EYAXr5
-----END CERTIFICATE-----
51 changes: 51 additions & 0 deletions labgrid/remote/certificates/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAqN3dy2ZzqIXfVvd+/I1s4pvksF54OuylsNiog9SdwPGN8/Qq
vB3VUq7t0pCgDm3lZHWBqwlFx++z9PehEC5hS5lNTYc55eZjDOFbiDmqc25m3Qzs
HoLaPgKV4NEGmnqbA5GYAJL+V1enEuQfMCOBvlojkR0IGFzreZJB3gOVlHRO1VU0
YzQifo4PyS8IPbVdbwu/EUoLNU/I6WRjYo4x+FmDuDbVWOqXxkE9kKRbTruFLyjX
YhTIkL/9ZlRYVXSwOEcUS6uDBr9HNSDyyfCGIZD5DoE1N29mDbpfhKPwW7fUtTP1
bHYdztOq2yY2gOEZjqI+7tPwOct4bHOxsEAXbwiNPHWUdFPCHD+eG/l7QtDn8IT0
Xe7piw5jC+PnGbSmuVXF2D66+axYol0BMgrPWSjmsbVt4Q7wYJv0VpniykE1ELhf
3R8/AI1jFJ4Dgib6U+acw8Z7+a3ONUNM9GumglR133QQuSh/uNXJaPhcGeYWHXmX
T7WWI/UTL0/TOboe6hk2KsYdsmvI/KpuYXikUDe37mmy+nLk6HX07ZLMD3fkt8sf
5tkqR3jpDuI7PXl1sEDVsl9tP0SWjMK9oZM0uD0SVe2BvaYBDSjNO3tjta1GIeYp
RKjk4GeHlf3IGEWCSYV5JokC0VaycV+quaAv0k5VByS3QfOEFtnt/7mc8ksCAwEA
AQKCAgEAn1c7QgKagBpSdC11lbmdVPblA8cgi/lhH05RNJQbh0RnPhrXeEpuUGbf
4iC15uer3O9EO6+0OMTmefBv+mTJShyN5OoEp/qM3EqJpDFFtUYnqc3Xv7KZXIn0
Av85y+qE+wkW9PO/K4t6C0lWZIYclxFXHkbWrKaBS2XG4UdgjYRyHrsXg8ReCCzk
mGHY1OGeGHptAFNt4BA49IHVhdnHLSDKObkD97LlJB3LigCMZ+5p7eYL1nDmEDAZ
W8Wa1IgXAAOSExTzvhofhvJgJkzfRC0X1af2Hyjuk2WZW/+VffYosBMnMgECf3cb
cU7Nfy7ofr55w8IYm3BzYWKJ+FWBxao9WQuCLsWJuHN5oyOx0ZG4BmT7Fku+K8h3
3YZ6Bn3zGV5MQ6hJQaupgT/rMySYptYfG/w+kHgK0pBcaiBHPmQPv1pThaUoQi6L
oN4urtQsf80fUDzIL+piI6sS9vKsvwiB6N+TqiBGFpatuODOeElGY4wPtUIx8gkp
+K8CuWjaHtLGeAgJAxAtS81ZXT+H0RxnsANcBTApRFHX9GEWzR8vjTCTfVQgk03A
tjNNCnXJxgD6TXYlEicZsH0dqQnoU+jPZW8Fl/ED562Z5VjZaiTeRmBpEAKcw5RG
pDG3t2OAKMI6R5mmAw00dQh9WynKFEoYNfaF7SPNz6tAb76QmgECggEBAOAp4yWu
OOAvAJ24lJkHC9/C0CBTf/O4VLZ4CXprYCadATCis7D1ePxcsJc7xMws/tDwIedO
OGukwK1zW5YyHzh2bePD0JDFkoE547PFXM6Yyb6e7qaL+vA4yOROPuJZR8pwMwdG
xy0ZHGPs/EK7FjKbFZG7qb06vRyxOKD17/3zhuOmZ1+6oRtRYCZGVUSz7TPfyDK8
H59cPMpA4WoawyTGyhpTQY4GBxbXA5Q8v6mUpu5mBzAAIp5MZUAK1dEDEQUwHCUy
gmYRef3H5IiKW+6c4ICLpUIk52DKFVpO3VwbIHxEYaF8Xz0CYKjGlpSBnbpTMjU5
UueSeOeopxWRBpECggEBAMDZf9MQtnwmbIR6utpOgT5V+YZ39AJktllcLlVADyoM
iYJwkF3DeXKJooQUkL9pzoaRekxCLlcC/J1vlVtQXgWStTPHKx8TMr0VuGRh/dtq
AFi+lq5PDn5z6o+mipeo00Gfd24xsi5VwkdR7ZwZD8pFZLEAZ020Z5gVpxjcMYLc
eCcIuw97VIFY9gXCAE9W6qXR3yohipCTg8BAcN2Z/Zy33+nCUlXQbtIwwtOT3JVP
NBDLrRqvHUL0JjlRNKTpiCYvZbP+7N2o3ZxG5okkcvzSRl66w7dfLVkYRrbUy8nX
+YkHKJKOE5Gs4HEAvEjtNAfvBUrp8tkYjI4fWQrXsRsCggEAcqi6SSHOcc1Y8VPi
nkueZTwOnRpYzl8w5YyMvJODwPx6CViPtSo6UktPAGxQA2fYhyLtFJVMArNo4s+o
vzCwC394QhJ88jA8+eCUefWvvPUl7Fz7ETF0j79b8nubasfkEsZFM6meY5D+lpY3
iiKL/iKZa8ujzOjopm532s0xjqIsEvGg2rRph8Gd/rXnE5c881W530memzLg3UtG
gbFis8MCyWhglba7lZExgXd5SdKBeFuzvXe0PWgyOgnQyHJbGF49Z0FotbCmx4qh
eL3cvDZ+FwJW63hY6Yc0WNcSHvS5LxcDIUiuplQ7ANljWF7cQNwhSFwj7dNcCJKZ
tExUIQKCAQAEfkzbJx2JYP/QSmfGJGQghrJMrsjRsXUKOfqeY+K2kRo3HtZOSPqw
b4KI303MF/QG8KbP1g7sWhZ2uJ3bRdEbAiMUtMRNcg4Rl8r3E81talfduXsbTp5A
1gSWGkRKalWZxtRqjd/f8oGXVdJae78BcIJ7GU5O4jAzu/Vrv92rdeWayzpIjxAV
/3OkCLQnJRhMispPWf63hahhN18p2qetGh+ue6eddkDOxvITKfPOysykw4oiAAiH
gdbOKRU37nUMprgQ7JSqSX/4XzKJ6X6AY4neNS3QPPh6hfVH10d0SYL37WHFoGfW
Uhfcqi646EX5FVmjODY/VrIXsaVKemIXAoIBAGQi35JOilMqHDWuJPq4LyOUxvKp
hnxA38Thx9Pvy2uvlJx6VwjyuBzuY4+qhinnSgKvIzAmS4kjFguuwPIE+WzhWRHu
D2GyeFCPTmMPLC76NIxyB6tZu4RQgKpF9e5+jPrVXLhd8kopPLUD729/c3iyZrcY
SU2tB4gGMPkREOqLn/fOZ/QPxzbOD4Qi2yxqF0Gy2O8T493Ikc9DW5LMZeakwFt7
e2jp2TkFIdJQ7ju93BRhv1rvum/LCgxxKD5i1zvIONBAoQBgbhC5gKkpx55NVZFG
Y+EnHOzFarlsWKu8akQA7BY1AgTKtBXCuu/W3NEWowPhmjzmdbQ/ener4ik=
-----END RSA PRIVATE KEY-----
21 changes: 17 additions & 4 deletions labgrid/remote/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
)
from .. import Environment, Target, target_factory
from ..exceptions import NoDriverFoundError, NoResourceFoundError, InvalidConfigError
from .authentication import SERVER_CERTIFICATE, CustomAuthMetadataPlugin
from .generated import labgrid_coordinator_pb2, labgrid_coordinator_pb2_grpc
from ..resource.remote import RemotePlaceManager, RemotePlace
from ..util import diff_dict, flat_dict, dump, atomic_replace, labgrid_version, Timeout
Expand Down Expand Up @@ -99,10 +100,21 @@ def __attrs_post_init__(self):
("grpc.http2.max_pings_without_data", 0), # no limit
]

self.channel = grpc.aio.insecure_channel(
target=self.address,
options=channel_options,
)
if self.args.auth:
call_credentials = grpc.metadata_call_credentials(CustomAuthMetadataPlugin(), name="auth")
channel_credentials = grpc.ssl_channel_credentials(SERVER_CERTIFICATE)
composite_credentials = grpc.composite_channel_credentials(channel_credentials, call_credentials)

self.channel = grpc.aio.secure_channel(
target=self.address,
credentials=composite_credentials,
options=channel_options,
)
else:
self.channel = grpc.aio.insecure_channel(
target=self.address,
options=channel_options,
)
self.stub = labgrid_coordinator_pb2_grpc.CoordinatorStub(self.channel)

self.out_queue = asyncio.Queue()
Expand Down Expand Up @@ -1699,6 +1711,7 @@ def main():
)
parser.add_argument("-v", "--verbose", action="count", default=0)
parser.add_argument("-P", "--proxy", type=str, help="proxy connections via given ssh host")
parser.add_argument("-A", "--auth", action="store_true", default=False, help="enable gRPC authentication")
subparsers = parser.add_subparsers(
dest="command",
title="available subcommands",
Expand Down
20 changes: 17 additions & 3 deletions labgrid/remote/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
TAG_KEY,
TAG_VAL,
)
from .authentication import SERVER_CERTIFICATE, SERVER_CERTIFICATE_KEY, SignatureValidationInterceptor
from .scheduler import TagSet, schedule
from .generated import labgrid_coordinator_pb2
from .generated import labgrid_coordinator_pb2_grpc
Expand Down Expand Up @@ -957,7 +958,7 @@ async def GetReservations(self, request: labgrid_coordinator_pb2.GetReservations
return labgrid_coordinator_pb2.GetReservationsResponse(reservations=reservations)


async def serve(listen, cleanup) -> None:
async def serve(listen, authenticate, cleanup) -> None:
# It seems since https://github.com/grpc/grpc/pull/34647, the
# ping_timeout_ms default of 60 seconds overrides keepalive_timeout_ms,
# so set it as well.
Expand All @@ -973,6 +974,7 @@ async def serve(listen, cleanup) -> None:
]
server = grpc.aio.server(
options=channel_options,
interceptors= ( (SignatureValidationInterceptor(),) if authenticate else ()),
)
coordinator = Coordinator()
labgrid_coordinator_pb2_grpc.add_CoordinatorServicer_to_server(coordinator, server)
Expand All @@ -993,7 +995,18 @@ async def serve(listen, cleanup) -> None:
except ImportError:
logging.info("Module grpcio-channelz not available")

server.add_insecure_port(listen)
if authenticate:
server_credentials = grpc.ssl_server_credentials(
(
(
SERVER_CERTIFICATE_KEY,
SERVER_CERTIFICATE,
),
)
)
server.add_secure_port(listen, server_credentials)
else:
server.add_insecure_port(listen)
logging.debug("Starting server")
await server.start()

Expand All @@ -1020,6 +1033,7 @@ def main():
help="coordinator listening host and port",
)
parser.add_argument("-d", "--debug", action="store_true", default=False, help="enable debug mode")
parser.add_argument("-A", "--auth", action="store_true", default=False, help="enable gRPC authentication")

args = parser.parse_args()

Expand All @@ -1031,7 +1045,7 @@ def main():
cleanup = []
loop.set_debug(True)
try:
loop.run_until_complete(serve(args.listen, cleanup))
loop.run_until_complete(serve(args.listen, args.auth, cleanup))
finally:
if cleanup:
loop.run_until_complete(*cleanup)
Expand Down
21 changes: 17 additions & 4 deletions labgrid/remote/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import attr
import grpc

from .authentication import SERVER_CERTIFICATE, CustomAuthMetadataPlugin
from .config import ResourceConfig
from .common import ResourceEntry, queue_as_aiter
from .generated import labgrid_coordinator_pb2, labgrid_coordinator_pb2_grpc
Expand Down Expand Up @@ -798,10 +799,20 @@ def __init__(self, config) -> None:
if urlsplit(f"//{config['coordinator']}").port is None:
config["coordinator"] += ":20408"

self.channel = grpc.aio.insecure_channel(
target=config["coordinator"],
options=channel_options,
)
if config["authentication"]:
call_credentials = grpc.metadata_call_credentials(CustomAuthMetadataPlugin(), name="auth")
channel_credentials = grpc.ssl_channel_credentials(SERVER_CERTIFICATE)
composite_credentials = grpc.composite_channel_credentials(channel_credentials, call_credentials)

self.channel = grpc.aio.secure_channel(
target=config["coordinator"],
credentials=composite_credentials,
options=channel_options,)
else:
self.channel = grpc.aio.insecure_channel(
target=config["coordinator"],
options=channel_options,
)
self.stub = labgrid_coordinator_pb2_grpc.CoordinatorStub(self.channel)
self.out_queue = asyncio.Queue()
self.pump_task = None
Expand Down Expand Up @@ -1044,6 +1055,7 @@ def main():
help="enable isolated mode (always request SSH forwards)",
)
parser.add_argument("resources", metavar="RESOURCES", type=str, help="resource config file name")
parser.add_argument("-A", "--auth", action="store_true", default=False, help="enable gRPC authentication")

args = parser.parse_args()

Expand All @@ -1055,6 +1067,7 @@ def main():
"resources": args.resources,
"coordinator": args.coordinator,
"isolated": args.isolated,
"authentication": args.auth,
}

print(f"exporter name: {config['name']}")
Expand Down

0 comments on commit 7a2b399

Please sign in to comment.