Loading .gitignore +1 −0 Original line number Diff line number Diff line .idea build cmake-build-debug ssh_client/test_asure.py No newline at end of file server_side/dockerfiles/Dockerfile.python +12 −8 Original line number Diff line number Diff line FROM ubuntu:22.04 AS no2fa FROM ubuntu:20.04 AS no2fa ARG DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Moscow RUN apt-get update && apt-get install -y ssh libpam-python curl python2 sudo vim python2-dev build-essential libssl1.0 ARG TEST_USER=test ENV TZ=America/New_York RUN apt-get update && apt-get install -y ssh libpam-python curl python2 sudo vim python2-dev build-essential RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py && python2 get-pip.py RUN apt-get install -y libffi-dev RUN apt-get install -y libffi-dev libssl-dev RUN pip2 config set global.target /lib/python2.7 \ && pip2 install requests \ && pip2 install pyjwt==1.7.1 \ && pip2 install cryptography==2.3 RUN useradd test RUN mkhomedir_helper test RUN echo test:123 | chpasswd env TEST_USER=$TEST_USER RUN useradd $TEST_USER RUN mkhomedir_helper $TEST_USER RUN echo $TEST_USER:123 | chpasswd RUN mkdir /run/sshd COPY python/oidc_pam.py /etc/security/oidc/oidc_pam.py Loading server_side/oidc-pam.json +2 −16 Original line number Diff line number Diff line [{ "provider": "keycloak", "verification_type": "jwks_url", "client_id": "galaxy", "client_secret":"coR3eIu4hEaxNwveSbXjsiHdHijYtRuf", "jwks_url": "http://localhost:8084/realms/master/protocol/openid-connect/certs", "introspection_url": "http://host.docker.internal:8080/realms/ndip/protocol/openid-connect/token/introspect", "check_2fa": false, "enable_log": true, "log_file": "/tmp/oidc.log" }, { "provider": "azure", "verification_type": "jwks_url", "client_id": "galaxy", "client_secret":"coR3eIu4hEaxNwveSbXjsiHdHijYtRuf", "jwks_url": "https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys", "jwks_url": "https://login.microsoftonline.com/db3dbd43-4c4b-4544-9f8a-0553f9f5f25e/discovery/v2.0/keys", "introspection_url": "", "check_2fa": false, "enable_log": true, "log_file": "/tmp/oidc.log" }] No newline at end of file } server_side/python/oidc_pam.py +10 −19 Original line number Diff line number Diff line Loading @@ -9,14 +9,13 @@ import base64 import json import jwt import os import sys import requests import logging from cryptography.hazmat.backends import default_backend from cryptography.x509 import load_der_x509_certificate logging.basicConfig(filename='oidc.log', encoding='utf-8', level=logging.DEBUG) logging.basicConfig(filename='/tmp/oidc.log', encoding='utf-8', level=logging.DEBUG) def logit(data): Loading Loading @@ -64,6 +63,7 @@ def pam_sm_authenticate(pamh, _flags, _argv): ''' # build access token return pamh.PAM_SUCCESS use_first_pass = 'use_first_pass' in _argv # get user&token Loading Loading @@ -92,11 +92,11 @@ def pam_sm_authenticate(pamh, _flags, _argv): except pamh.exception as error: return error.pam_result return verify_token_jwt(pamh, user, access_token, None) return verify_token_jwt(pamh, user, access_token) def verify_token_jwt(pamh, user, access_token, jwt_options): config = load_config_jwt(pamh) def verify_token_jwt(pamh, user, access_token): config = load_config() try: # Obtain appropriate cert from JWK URI jwks_url = config['jwks_url'] Loading @@ -111,7 +111,7 @@ def verify_token_jwt(pamh, user, access_token, jwt_options): x5c = key['x5c'][0] break else: raise jwt.DecodeError(f'Cannot find kid={kid}') raise jwt.DecodeError('Cannot find kid ' + key_id) cert = load_der_x509_certificate(base64.b64decode(x5c), default_backend()) # Decode token (exp date is checked automatically) Loading @@ -119,10 +119,10 @@ def verify_token_jwt(pamh, user, access_token, jwt_options): access_token, key=cert.public_key(), algorithms=['RS256'], options=jwt_options options={'exp': True, 'verify_aud': False} ) # Check if correct user if decoded_token['preferred_username'] != user: if decoded_token['preferred_username'].split('@',1)[0] != user: logit('SSH user does not match token user: %s (ssh) !=v %s (token)' % (user, decoded_token['preferred_username'])) return pamh.PAM_AUTH_ERR Loading @@ -139,8 +139,7 @@ def verify_token_jwt(pamh, user, access_token, jwt_options): logit('Login successful for user %s, token %s' % (user, access_token)) return pamh.PAM_SUCCESS def load_config(pamh): # Load config file def load_config(): config_dpath = os.path.dirname(os.path.realpath(__file__)) config_fpath = os.path.join(config_dpath, 'oidc-pam.json') config_fd = open(config_fpath, 'r') Loading @@ -148,11 +147,3 @@ def load_config(pamh): config_fd.close() config = json.loads(config) return config def load_config_jwt(pamh): try: config = load_config(pamh) return next((config_item for config_item in config if config_item['verification_type'] == "jwks_url")) except Exception as error: logit('Error loading configuration for jwt verification: %s' % error) return pamh.PAM_AUTH_ERR server_side/start_no2fa.sh +1 −1 Original line number Diff line number Diff line #!/bin/bash set -e chown test: -R /home/test chown $TEST_USER: -R /home/$TEST_USER cd /tmp/oidc python3 /tmp/oidc/update_oidc_config.py Loading Loading
.gitignore +1 −0 Original line number Diff line number Diff line .idea build cmake-build-debug ssh_client/test_asure.py No newline at end of file
server_side/dockerfiles/Dockerfile.python +12 −8 Original line number Diff line number Diff line FROM ubuntu:22.04 AS no2fa FROM ubuntu:20.04 AS no2fa ARG DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Moscow RUN apt-get update && apt-get install -y ssh libpam-python curl python2 sudo vim python2-dev build-essential libssl1.0 ARG TEST_USER=test ENV TZ=America/New_York RUN apt-get update && apt-get install -y ssh libpam-python curl python2 sudo vim python2-dev build-essential RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py && python2 get-pip.py RUN apt-get install -y libffi-dev RUN apt-get install -y libffi-dev libssl-dev RUN pip2 config set global.target /lib/python2.7 \ && pip2 install requests \ && pip2 install pyjwt==1.7.1 \ && pip2 install cryptography==2.3 RUN useradd test RUN mkhomedir_helper test RUN echo test:123 | chpasswd env TEST_USER=$TEST_USER RUN useradd $TEST_USER RUN mkhomedir_helper $TEST_USER RUN echo $TEST_USER:123 | chpasswd RUN mkdir /run/sshd COPY python/oidc_pam.py /etc/security/oidc/oidc_pam.py Loading
server_side/oidc-pam.json +2 −16 Original line number Diff line number Diff line [{ "provider": "keycloak", "verification_type": "jwks_url", "client_id": "galaxy", "client_secret":"coR3eIu4hEaxNwveSbXjsiHdHijYtRuf", "jwks_url": "http://localhost:8084/realms/master/protocol/openid-connect/certs", "introspection_url": "http://host.docker.internal:8080/realms/ndip/protocol/openid-connect/token/introspect", "check_2fa": false, "enable_log": true, "log_file": "/tmp/oidc.log" }, { "provider": "azure", "verification_type": "jwks_url", "client_id": "galaxy", "client_secret":"coR3eIu4hEaxNwveSbXjsiHdHijYtRuf", "jwks_url": "https://login.microsoftonline.com/{tenant}/discovery/v2.0/keys", "jwks_url": "https://login.microsoftonline.com/db3dbd43-4c4b-4544-9f8a-0553f9f5f25e/discovery/v2.0/keys", "introspection_url": "", "check_2fa": false, "enable_log": true, "log_file": "/tmp/oidc.log" }] No newline at end of file }
server_side/python/oidc_pam.py +10 −19 Original line number Diff line number Diff line Loading @@ -9,14 +9,13 @@ import base64 import json import jwt import os import sys import requests import logging from cryptography.hazmat.backends import default_backend from cryptography.x509 import load_der_x509_certificate logging.basicConfig(filename='oidc.log', encoding='utf-8', level=logging.DEBUG) logging.basicConfig(filename='/tmp/oidc.log', encoding='utf-8', level=logging.DEBUG) def logit(data): Loading Loading @@ -64,6 +63,7 @@ def pam_sm_authenticate(pamh, _flags, _argv): ''' # build access token return pamh.PAM_SUCCESS use_first_pass = 'use_first_pass' in _argv # get user&token Loading Loading @@ -92,11 +92,11 @@ def pam_sm_authenticate(pamh, _flags, _argv): except pamh.exception as error: return error.pam_result return verify_token_jwt(pamh, user, access_token, None) return verify_token_jwt(pamh, user, access_token) def verify_token_jwt(pamh, user, access_token, jwt_options): config = load_config_jwt(pamh) def verify_token_jwt(pamh, user, access_token): config = load_config() try: # Obtain appropriate cert from JWK URI jwks_url = config['jwks_url'] Loading @@ -111,7 +111,7 @@ def verify_token_jwt(pamh, user, access_token, jwt_options): x5c = key['x5c'][0] break else: raise jwt.DecodeError(f'Cannot find kid={kid}') raise jwt.DecodeError('Cannot find kid ' + key_id) cert = load_der_x509_certificate(base64.b64decode(x5c), default_backend()) # Decode token (exp date is checked automatically) Loading @@ -119,10 +119,10 @@ def verify_token_jwt(pamh, user, access_token, jwt_options): access_token, key=cert.public_key(), algorithms=['RS256'], options=jwt_options options={'exp': True, 'verify_aud': False} ) # Check if correct user if decoded_token['preferred_username'] != user: if decoded_token['preferred_username'].split('@',1)[0] != user: logit('SSH user does not match token user: %s (ssh) !=v %s (token)' % (user, decoded_token['preferred_username'])) return pamh.PAM_AUTH_ERR Loading @@ -139,8 +139,7 @@ def verify_token_jwt(pamh, user, access_token, jwt_options): logit('Login successful for user %s, token %s' % (user, access_token)) return pamh.PAM_SUCCESS def load_config(pamh): # Load config file def load_config(): config_dpath = os.path.dirname(os.path.realpath(__file__)) config_fpath = os.path.join(config_dpath, 'oidc-pam.json') config_fd = open(config_fpath, 'r') Loading @@ -148,11 +147,3 @@ def load_config(pamh): config_fd.close() config = json.loads(config) return config def load_config_jwt(pamh): try: config = load_config(pamh) return next((config_item for config_item in config if config_item['verification_type'] == "jwks_url")) except Exception as error: logit('Error loading configuration for jwt verification: %s' % error) return pamh.PAM_AUTH_ERR
server_side/start_no2fa.sh +1 −1 Original line number Diff line number Diff line #!/bin/bash set -e chown test: -R /home/test chown $TEST_USER: -R /home/$TEST_USER cd /tmp/oidc python3 /tmp/oidc/update_oidc_config.py Loading