├── .github └── CODEOWNERS ├── .gitignore ├── .k8s-auth-client ├── LICENSE.TXT ├── README.md └── k8s-auth-client.sh /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | @vimond/platform -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml -------------------------------------------------------------------------------- /.k8s-auth-client: -------------------------------------------------------------------------------- 1 | # Issuer URL, for Keycloak this will be the base URL for the realm 2 | K8S_OIDC_ISSUER=https://www.example.com/auth/realms/example_realm 3 | 4 | K8S_OIDC_CLIENT_ID=example_client 5 | K8S_OIDC_CLIENT_SECRET=secret_value 6 | 7 | # OIDC token endpoint, for Keycloak it's the base URL for the realm + '/protocol/openid-connect/token' 8 | K8S_OIDC_TOKEN_ENDPOINT=https://www.example.com/auth/realms/example_realm/protocol/openid-connect/token 9 | 10 | # The following values are optional - use when not running on MacOS. 11 | # Remember to limit read access of this config file in such cases. 12 | K8S_AUTH_USERNAME=username 13 | K8S_AUTH_PASSWORD=password 14 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Vimond Media Solutions 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes OIDC authentication client 2 | 3 | This script is intended to be used as a helper script when using OIDC authentication together with Kubernetes. 4 | 5 | The script authenticates with an OIDC compliant identity provider using the Resource Owner Password Credentials grant flow with 6 | a confidential client. It then sets the id and refresh tokens in the Kubernetes config file for the selected user, 7 | ready to be used by the Kubernetes kubectl command. The Kubernetes OIDC authenticator will attempt to fetch 8 | new tokens as needed. 9 | 10 | This script has been tested using [Keycloak](http://www.keycloak.org/) 11 | 12 | Please note that this script requires that a MFA (TOTP) code be used, for added security. 13 | 14 | ## Installation 15 | 16 | Install the jq dependency (https://stedolan.github.io/jq/download/) if you don't already have it. For MacOS: 17 | 18 | `brew install jq` 19 | 20 | Copy the [k8s-auth-client.sh](k8s-auth-client.sh) script somewhere on your path, and set it executable. 21 | 22 | `chmod u+x k8s-auth-client.sh` 23 | 24 | Create a config file named [.k8s-auth-client](.k8s-auth-client) in your `~/.kube/` folder. Edit the values to fit your setup. 25 | 26 | MacOS specific configuration: 27 | 28 | ### 29 | 30 | Add a Keychain entry for the identity provider account you use to authenticate as a generic password. 31 | Name the entry `k8s-auth-client`, with the identity provider username in the "Account" field. 32 | 33 | ## Usage 34 | 35 | `k8s-auth-client.sh ` 36 | 37 | If you have set a MacOS Keychain password as described under installation these credentials will be fetched 38 | and used automatically. Any credentials configured in the config file will override these. If using the config 39 | file to store credentials please remember to restrict access to it appropriately. 40 | 41 | ## Keycloak 42 | 43 | As of keycloak 6.x (and other versions). 44 | 45 | You should create a client for your cluster. The client needs to be a `confidential` client. 46 | You need to enable `Direct access grants enabled` and `Service accounts enabled` on the Client page. 47 | You can use a custom group mapper to map groups with full path to your id token. 48 | 49 | WARNING: A token that takes long to expire is a security issue. You can increase the refresh token expiration via Realm/Tokens page, option `SSO Session Idle`. 50 | -------------------------------------------------------------------------------- /k8s-auth-client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | if [ "$#" -ne 1 ] ; then 3 | echo "Usage: k8s-auth-client.sh " >&2 4 | exit 1 5 | fi 6 | 7 | KUBE_CONFIG_USERNAME=$1 8 | 9 | #Basic error handling 10 | set -o errexit 11 | set -o pipefail 12 | 13 | source ~/.kube/$KUBE_CONFIG_USERNAME.k8s-auth-client 14 | 15 | if [[ -z $K8S_AUTH_USERNAME || -z $K8S_AUTH_PASSWORD ]]; then 16 | #fetch password from keychain 17 | K8S_AUTH_USERNAME=$(security find-generic-password -s k8s-auth-client | grep 'acct' | cut -d \" -f4) 18 | K8S_AUTH_PASSWORD=$(security find-generic-password -s k8s-auth-client -w) 19 | fi 20 | 21 | set -o nounset 22 | 23 | 24 | read -p 'MFA code:' TOTP 25 | 26 | #fetch and parse tokens from Keycloak 27 | KEYCLOAK_RESPONSE=$(curl -# --data "grant_type=password&client_id=$K8S_OIDC_CLIENT_ID&username=$K8S_AUTH_USERNAME&password=$K8S_AUTH_PASSWORD&scope=openid&client_secret=$K8S_OIDC_CLIENT_SECRET&totp=$TOTP" $K8S_OIDC_TOKEN_ENDPOINT) 28 | K8S_REFRESH_TOKEN=$(echo ${KEYCLOAK_RESPONSE} | jq -r '.refresh_token') 29 | K8S_ID_TOKEN=$(echo ${KEYCLOAK_RESPONSE} | jq -r '.id_token') 30 | 31 | #set Kubernetes credentials 32 | kubectl config set-credentials $KUBE_CONFIG_USERNAME \ 33 | --auth-provider=oidc \ 34 | --auth-provider-arg=idp-issuer-url=$K8S_OIDC_ISSUER \ 35 | --auth-provider-arg=client-id=$K8S_OIDC_CLIENT_ID \ 36 | --auth-provider-arg=client-secret=$K8S_OIDC_CLIENT_SECRET \ 37 | --auth-provider-arg=refresh-token=$K8S_REFRESH_TOKEN \ 38 | --auth-provider-arg=id-token=$K8S_ID_TOKEN 39 | --------------------------------------------------------------------------------