Loading server_side/.dockerignore→.dockerignore +0 −0 File moved. View file .gitlab-ci.yml +6 −7 Original line number Diff line number Diff line Loading @@ -5,7 +5,6 @@ variables: NO2FA_URL: "${CI_REGISTRY_IMAGE}/ubuntu_sshd" WITH2FA_URL: "${CI_REGISTRY_IMAGE}/opensuse_sshd_2fa" # This import is for the func_rse_docker_* functions before_script: - curl https://code.ornl.gov/rse-deployment/rse-sharables/raw/master/rse-bash-modules.sh -O - source rse-bash-modules.sh Loading @@ -24,8 +23,8 @@ build-docker: script: - docker login --username=$CI_REGISTRY_USER --password=$CI_REGISTRY_PASSWORD $CI_REGISTRY - if [ $CI_COMMIT_REF_NAME == "main" ]; then export IMAGE_PREFIX=""; fi - docker build -f server_side/dockerfiles/Dockerfile.ubuntu -t no2fa --target no2fa ./server_side - docker build -f server_side/dockerfiles/Dockerfile.opensuse -t with2fa --target with2fa ./server_side - docker build -f dockerfiles/Dockerfile.ubuntu -t no2fa --target no2fa . - docker build -f dockerfiles/Dockerfile.opensuse -t with2fa --target with2fa . - docker tag no2fa $NO2FA_URL$IMAGE_PREFIX:latest - docker tag with2fa $WITH2FA_URL$IMAGE_PREFIX:latest - docker push $NO2FA_URL$IMAGE_PREFIX:latest Loading @@ -36,10 +35,10 @@ build-docker: build-packages: stage: build script: - docker build -f server_side/dockerfiles/Dockerfile.ubuntu -t ubuntu22 --target package ./server_side - docker run --rm -v `pwd`:/tmp ubuntu22 bash -c "cp /src/c/build/*.deb /tmp" - docker build -f server_side/dockerfiles/Dockerfile.opensuse -t opensuse --target package ./server_side - docker run --rm -v `pwd`:/tmp opensuse bash -c "cp /src/c/build/*.rpm /tmp" - docker build -f dockerfiles/Dockerfile.ubuntu -t ubuntu22 --target package . - docker run --rm -v `pwd`:/tmp ubuntu22 bash -c "cp /src/build/*.deb /tmp" - docker build -f dockerfiles/Dockerfile.opensuse -t opensuse --target package . - docker run --rm -v `pwd`:/tmp opensuse bash -c "cp /src/build/*.rpm /tmp" - fname=`ls *.rpm | head -n 1` - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file $fname "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/rpm/0.3.0/$fname"' - fname=`ls *.deb | head -n 1` Loading README.md 0 → 100644 +51 −0 Original line number Diff line number Diff line # OIDC-based Authentication This project enables user authentication on servers using OpenID Connect tokens. It includes a PAM module for SSH login via an OIDC token and a utility for executing commands and copying files on behalf of a user, also utilizing an OIDC token for authentication. ## The PAM Module The PAM module utilizes keyboard-interactive authentication, prompting the user to supply an OIDC token when attempting to SSH into a machine with the module installed. Since tokens can grow large and potentially exceed the `PAM_MAX_RESP_SIZE` value, multiple prompts are provided. Users should split their tokens into multiple parts for proper connection. Note: Users will rarely, if ever, need to directly interact with this PAM module, as it's typically automated. But an [example script](examples/ssh_connect.py) demonstrates how this can be handled. ## Run-as-User Utility This utility allows the execution of commands on behalf of a user. It verifies the user token, extracts the username from it, searches for the corresponding `uid`, and switches to it before executing the command. The utility needs to have `setuid` set to be able to do that. ## Configuration ### Configuration File To properly configure the PAM module and utility, the `oidc-config.json` file must be set up with the correct parameters. See the [oidc-pam.json](config/oidc-pam.json) example. ### SSH/PAM Configuration For the PAM module, SSH server and PAM configuration must be properly configured. Refer to [sshd.conf](config/sshd_pam.conf) for SSH configuration and [sshd](config/sshd) for PAM configuration. ## Building You can build locally using `CMake` or within Docker containers. Refer to the corresponding Docker files for [Ubuntu](dockerfiles/Dockerfile.ubuntu) and [openSUSE](dockerfiles/Dockerfile.opensuse). Both RPM and DEB packages are built within these images. GitLab CI/CD pipelines are utilized for package generation, but manual generation is also possible. ## Testing Both the utility and PAM modules can be tested easily. First, prepare a config file with OIDC provider information. See the [oidc-pam.json](config/oidc-pam.json) example. For PAM testing, run one of the provided containers (mounting the config file to `/tmp/oidc/oidc-pam.json`) and attempt SSH login using the provided [example script](examples/ssh_connect.py). You cannot directly copy/paste token due to the size limitations described above. For the `run_as_user` utility, simply execute the binary file with the necessary parameters. ReadMe.mddeleted 100644 → 0 +0 −30 Original line number Diff line number Diff line # 2FA ## Links * https://goteleport.com/blog/ssh-2fa-tutorial/ * https://github.com/google/google-authenticator-libpam ## Getting secrets/link to a QR code for Google Authenticator ``` docker exec <container_id> cat /home/test/auth/auth_secrets ``` # PAM module in Python https://developers.onelogin.com/authentication/tools/linux-ssh-pam-module # Keycloak (just for manual tests, now in code) get token ```curl -d 'client_id=ndip' -d 'client_secret=ZLrwMJePHNqDbHzZOLwdQrHjaByI4mhK' -d 'username=gtest' -d 'password=1234' -d 'grant_type=password' 'http://localhost:8080/realms/NDIP/protocol/openid-connect/token'``` refresh token ```curl -X POST -d 'client_id=ndip' -d 'client_secret=ZLrwMJePHNqDbHzZOLwdQrHjaByI4mhK' -d 'grant_type=refresh_token' -d refresh_token=$rtoken http://localhost:8080/realms/NDIP/protocol/openid-connect/token``` introspect token curl -d token=$token -d 'client_id=ndip' -d 'client_secret=ZLrwMJePHNqDbHzZOLwdQrHjaByI4mhK' http://localhost:8080/realms/NDIP/protocol/openid-connect/token/introspect config/oidc-pam.json 0 → 100644 +17 −0 Original line number Diff line number Diff line { "auth": [ { "jwks_url": "jwks_url_1", "name_field": "username", "name_separator": "" }, { "jwks_url": "jwks_url_2", "name_field": "preferred_username", "name_separator": "@" } ], "enable_log": true, "cache_folder": "/var/tmp/oidc_cache", "log_file": "/var/log/oidc_log" } Loading
.gitlab-ci.yml +6 −7 Original line number Diff line number Diff line Loading @@ -5,7 +5,6 @@ variables: NO2FA_URL: "${CI_REGISTRY_IMAGE}/ubuntu_sshd" WITH2FA_URL: "${CI_REGISTRY_IMAGE}/opensuse_sshd_2fa" # This import is for the func_rse_docker_* functions before_script: - curl https://code.ornl.gov/rse-deployment/rse-sharables/raw/master/rse-bash-modules.sh -O - source rse-bash-modules.sh Loading @@ -24,8 +23,8 @@ build-docker: script: - docker login --username=$CI_REGISTRY_USER --password=$CI_REGISTRY_PASSWORD $CI_REGISTRY - if [ $CI_COMMIT_REF_NAME == "main" ]; then export IMAGE_PREFIX=""; fi - docker build -f server_side/dockerfiles/Dockerfile.ubuntu -t no2fa --target no2fa ./server_side - docker build -f server_side/dockerfiles/Dockerfile.opensuse -t with2fa --target with2fa ./server_side - docker build -f dockerfiles/Dockerfile.ubuntu -t no2fa --target no2fa . - docker build -f dockerfiles/Dockerfile.opensuse -t with2fa --target with2fa . - docker tag no2fa $NO2FA_URL$IMAGE_PREFIX:latest - docker tag with2fa $WITH2FA_URL$IMAGE_PREFIX:latest - docker push $NO2FA_URL$IMAGE_PREFIX:latest Loading @@ -36,10 +35,10 @@ build-docker: build-packages: stage: build script: - docker build -f server_side/dockerfiles/Dockerfile.ubuntu -t ubuntu22 --target package ./server_side - docker run --rm -v `pwd`:/tmp ubuntu22 bash -c "cp /src/c/build/*.deb /tmp" - docker build -f server_side/dockerfiles/Dockerfile.opensuse -t opensuse --target package ./server_side - docker run --rm -v `pwd`:/tmp opensuse bash -c "cp /src/c/build/*.rpm /tmp" - docker build -f dockerfiles/Dockerfile.ubuntu -t ubuntu22 --target package . - docker run --rm -v `pwd`:/tmp ubuntu22 bash -c "cp /src/build/*.deb /tmp" - docker build -f dockerfiles/Dockerfile.opensuse -t opensuse --target package . - docker run --rm -v `pwd`:/tmp opensuse bash -c "cp /src/build/*.rpm /tmp" - fname=`ls *.rpm | head -n 1` - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file $fname "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/rpm/0.3.0/$fname"' - fname=`ls *.deb | head -n 1` Loading
README.md 0 → 100644 +51 −0 Original line number Diff line number Diff line # OIDC-based Authentication This project enables user authentication on servers using OpenID Connect tokens. It includes a PAM module for SSH login via an OIDC token and a utility for executing commands and copying files on behalf of a user, also utilizing an OIDC token for authentication. ## The PAM Module The PAM module utilizes keyboard-interactive authentication, prompting the user to supply an OIDC token when attempting to SSH into a machine with the module installed. Since tokens can grow large and potentially exceed the `PAM_MAX_RESP_SIZE` value, multiple prompts are provided. Users should split their tokens into multiple parts for proper connection. Note: Users will rarely, if ever, need to directly interact with this PAM module, as it's typically automated. But an [example script](examples/ssh_connect.py) demonstrates how this can be handled. ## Run-as-User Utility This utility allows the execution of commands on behalf of a user. It verifies the user token, extracts the username from it, searches for the corresponding `uid`, and switches to it before executing the command. The utility needs to have `setuid` set to be able to do that. ## Configuration ### Configuration File To properly configure the PAM module and utility, the `oidc-config.json` file must be set up with the correct parameters. See the [oidc-pam.json](config/oidc-pam.json) example. ### SSH/PAM Configuration For the PAM module, SSH server and PAM configuration must be properly configured. Refer to [sshd.conf](config/sshd_pam.conf) for SSH configuration and [sshd](config/sshd) for PAM configuration. ## Building You can build locally using `CMake` or within Docker containers. Refer to the corresponding Docker files for [Ubuntu](dockerfiles/Dockerfile.ubuntu) and [openSUSE](dockerfiles/Dockerfile.opensuse). Both RPM and DEB packages are built within these images. GitLab CI/CD pipelines are utilized for package generation, but manual generation is also possible. ## Testing Both the utility and PAM modules can be tested easily. First, prepare a config file with OIDC provider information. See the [oidc-pam.json](config/oidc-pam.json) example. For PAM testing, run one of the provided containers (mounting the config file to `/tmp/oidc/oidc-pam.json`) and attempt SSH login using the provided [example script](examples/ssh_connect.py). You cannot directly copy/paste token due to the size limitations described above. For the `run_as_user` utility, simply execute the binary file with the necessary parameters.
ReadMe.mddeleted 100644 → 0 +0 −30 Original line number Diff line number Diff line # 2FA ## Links * https://goteleport.com/blog/ssh-2fa-tutorial/ * https://github.com/google/google-authenticator-libpam ## Getting secrets/link to a QR code for Google Authenticator ``` docker exec <container_id> cat /home/test/auth/auth_secrets ``` # PAM module in Python https://developers.onelogin.com/authentication/tools/linux-ssh-pam-module # Keycloak (just for manual tests, now in code) get token ```curl -d 'client_id=ndip' -d 'client_secret=ZLrwMJePHNqDbHzZOLwdQrHjaByI4mhK' -d 'username=gtest' -d 'password=1234' -d 'grant_type=password' 'http://localhost:8080/realms/NDIP/protocol/openid-connect/token'``` refresh token ```curl -X POST -d 'client_id=ndip' -d 'client_secret=ZLrwMJePHNqDbHzZOLwdQrHjaByI4mhK' -d 'grant_type=refresh_token' -d refresh_token=$rtoken http://localhost:8080/realms/NDIP/protocol/openid-connect/token``` introspect token curl -d token=$token -d 'client_id=ndip' -d 'client_secret=ZLrwMJePHNqDbHzZOLwdQrHjaByI4mhK' http://localhost:8080/realms/NDIP/protocol/openid-connect/token/introspect
config/oidc-pam.json 0 → 100644 +17 −0 Original line number Diff line number Diff line { "auth": [ { "jwks_url": "jwks_url_1", "name_field": "username", "name_separator": "" }, { "jwks_url": "jwks_url_2", "name_field": "preferred_username", "name_separator": "@" } ], "enable_log": true, "cache_folder": "/var/tmp/oidc_cache", "log_file": "/var/log/oidc_log" }