From e8733a37afe57650f1df4be95b2ba80fc0be6436 Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Wed, 24 Aug 2022 14:37:18 +0200 Subject: [PATCH] Update scripts for the self-hosted Oauth 2.0 Device Auth Grant support (#439) Support Oauth 2.0 Device Auth Grant in the self-hosted scripts. --- .../workflows/test-docker-compose-linux.yml | 23 +++++--- infrastructure_files/base.setup.env | 5 ++ infrastructure_files/configure.sh | 58 ++++++++++++++++--- infrastructure_files/management.json.tmpl | 15 ++++- infrastructure_files/setup.env.example | 12 ++-- infrastructure_files/tests/setup.env | 6 +- management/cmd/management.go | 3 +- management/server/config.go | 2 +- management/server/grpcserver.go | 2 +- 9 files changed, 93 insertions(+), 33 deletions(-) diff --git a/.github/workflows/test-docker-compose-linux.yml b/.github/workflows/test-docker-compose-linux.yml index aa7132249..6ec64c660 100644 --- a/.github/workflows/test-docker-compose-linux.yml +++ b/.github/workflows/test-docker-compose-linux.yml @@ -5,6 +5,12 @@ jobs: test: runs-on: ubuntu-latest steps: + - name: Install jq + run: sudo apt-get install -y jq + + - name: Install curl + run: sudo apt-get install -y curl + - name: Install Go uses: actions/setup-go@v2 with: @@ -28,30 +34,31 @@ jobs: working-directory: infrastructure_files run: bash -x configure.sh env: - CI_NETBIRD_AUTH_AUTHORITY: ${{ secrets.CI_NETBIRD_AUTH_AUTHORITY }} CI_NETBIRD_AUTH_CLIENT_ID: ${{ secrets.CI_NETBIRD_AUTH_CLIENT_ID }} CI_NETBIRD_AUTH_AUDIENCE: testing.ci - CI_NETBIRD_AUTH_JWT_CERTS: ${{ secrets.CI_NETBIRD_AUTH_AUTHORITY }}.well-known/jwks.json - CI_NETBIRD_AUTH_SUPPORTED_SCOPES: openid + CI_NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT: https://example.eu.auth0.com/.well-known/openid-configuration CI_NETBIRD_USE_AUTH0: true - name: check values working-directory: infrastructure_files env: - CI_NETBIRD_AUTH_AUTHORITY: ${{ secrets.CI_NETBIRD_AUTH_AUTHORITY }} CI_NETBIRD_AUTH_CLIENT_ID: ${{ secrets.CI_NETBIRD_AUTH_CLIENT_ID }} CI_NETBIRD_AUTH_AUDIENCE: testing.ci - CI_NETBIRD_AUTH_JWT_CERTS: ${{ secrets.CI_NETBIRD_AUTH_AUTHORITY }}.well-known/jwks.json - CI_NETBIRD_AUTH_SUPPORTED_SCOPES: openid + CI_NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT: https://example.eu.auth0.com/.well-known/openid-configuration CI_NETBIRD_USE_AUTH0: true + CI_NETBIRD_AUTH_SUPPORTED_SCOPES: "openid profile email offline_access api email_verified" + CI_NETBIRD_AUTH_AUTHORITY: https://example.eu.auth0.com/ + CI_NETBIRD_AUTH_JWT_CERTS: https://example.eu.auth0.com/.well-known/jwks.json + CI_NETBIRD_AUTH_TOKEN_ENDPOINT: https://example.eu.auth0.com/oauth/token + CI_NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT: https://example.eu.auth0.com/oauth/device/code run: | grep AUTH_CLIENT_ID docker-compose.yml | grep $CI_NETBIRD_AUTH_CLIENT_ID grep AUTH_AUTHORITY docker-compose.yml | grep $CI_NETBIRD_AUTH_AUTHORITY grep AUTH_AUDIENCE docker-compose.yml | grep $CI_NETBIRD_AUTH_AUDIENCE - grep AUTH_SUPPORTED_SCOPES docker-compose.yml | grep $CI_NETBIRD_AUTH_SUPPORTED_SCOPES + grep AUTH_SUPPORTED_SCOPES docker-compose.yml | grep "$CI_NETBIRD_AUTH_SUPPORTED_SCOPES" grep USE_AUTH0 docker-compose.yml | grep $CI_NETBIRD_USE_AUTH0 grep NETBIRD_MGMT_API_ENDPOINT docker-compose.yml | grep "http://localhost:33073" - + - name: run docker compose up working-directory: infrastructure_files run: | diff --git a/infrastructure_files/base.setup.env b/infrastructure_files/base.setup.env index e8642f61d..cbd13116c 100644 --- a/infrastructure_files/base.setup.env +++ b/infrastructure_files/base.setup.env @@ -27,6 +27,8 @@ MGMT_VOLUMESUFFIX="mgmt" SIGNAL_VOLUMESUFFIX="signal" LETSENCRYPT_VOLUMESUFFIX="letsencrypt" +NETBIRD_AUTH_DEVICE_AUTH_PROVIDER="none" + # exports export NETBIRD_DOMAIN export NETBIRD_AUTH_CLIENT_ID @@ -40,6 +42,9 @@ export NETBIRD_MGMT_API_PORT export NETBIRD_MGMT_API_ENDPOINT export NETBIRD_MGMT_API_CERT_FILE export NETBIRD_MGMT_API_CERT_KEY_FILE +export NETBIRD_AUTH_DEVICE_AUTH_PROVIDER +export NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID +export NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT export TURN_USER export TURN_PASSWORD export TURN_MIN_PORT diff --git a/infrastructure_files/configure.sh b/infrastructure_files/configure.sh index 15c7b2dbe..563f88844 100755 --- a/infrastructure_files/configure.sh +++ b/infrastructure_files/configure.sh @@ -1,5 +1,21 @@ #!/bin/bash +if ! which curl > /dev/null 2>&1 +then + echo "This script uses curl fetch OpenID configuration from IDP." + echo "Please install curl and re-run the script https://curl.se/" + echo "" + exit 1 +fi + +if ! which jq > /dev/null 2>&1 +then + echo "This script uses jq to load OpenID configuration from IDP." + echo "Please install jq and re-run the script https://stedolan.github.io/jq/" + echo "" + exit 1 +fi + source setup.env source base.setup.env @@ -63,21 +79,49 @@ export MGMT_VOLUMENAME export SIGNAL_VOLUMENAME export LETSENCRYPT_VOLUMENAME -#backwards compatibility after migrating to generic OIDC -if [[ -z "${NETBIRD_AUTH_AUTHORITY}" ]]; then +#backwards compatibility after migrating to generic OIDC with Auth0 +if [[ -z "${NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT}" ]]; then + + if [[ -z "${NETBIRD_AUTH0_DOMAIN}" ]]; then + # not a backward compatible state + echo "NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT property must be set in the setup.env file" + exit 1 + fi + echo "It seems like you provided an old setup.env file." - echo "Since the release of v0.8.8, we introduced a new set of properties." + echo "Since the release of v0.8.10, we introduced a new set of properties." echo "The script is backward compatible and will continue automatically." echo "In the future versions it will be deprecated. Please refer to the documentation to learn about the changes http://netbird.io/docs/getting-started/self-hosting" - export NETBIRD_AUTH_AUTHORITY="https://${NETBIRD_AUTH0_DOMAIN}/" - export NETBIRD_AUTH_CLIENT_ID=${NETBIRD_AUTH0_CLIENT_ID} + export NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="https://${NETBIRD_AUTH0_DOMAIN}/.well-known/openid-configuration" export NETBIRD_USE_AUTH0="true" - export NETBIRD_AUTH_SUPPORTED_SCOPES="openid profile email api offline_access email_verified" export NETBIRD_AUTH_AUDIENCE=${NETBIRD_AUTH0_AUDIENCE} - export NETBIRD_AUTH_JWT_CERTS="https://${NETBIRD_AUTH0_DOMAIN}/.well-known/jwks.json" + export NETBIRD_AUTH_CLIENT_ID=${NETBIRD_AUTH0_CLIENT_ID} fi +echo "loading OpenID configuration from ${NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT} to the openid-configuration.json file" +curl "${NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT}" -q -o openid-configuration.json + +export NETBIRD_AUTH_AUTHORITY=$( jq -r '.issuer' openid-configuration.json ) +export NETBIRD_AUTH_JWT_CERTS=$( jq -r '.jwks_uri' openid-configuration.json ) +export NETBIRD_AUTH_SUPPORTED_SCOPES=$( jq -r '.scopes_supported | join(" ")' openid-configuration.json ) +export NETBIRD_AUTH_TOKEN_ENDPOINT=$( jq -r '.token_endpoint' openid-configuration.json ) +export NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT=$( jq -r '.device_authorization_endpoint' openid-configuration.json ) + +if [ $NETBIRD_USE_AUTH0 == "true" ] +then + export NETBIRD_AUTH_SUPPORTED_SCOPES="openid profile email offline_access api email_verified" +else + export NETBIRD_AUTH_SUPPORTED_SCOPES="openid profile email offline_access api" +fi + +if [[ ! -z "${NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID}" ]]; then + # user enabled Device Authorization Grant feature + export NETBIRD_AUTH_DEVICE_AUTH_PROVIDER="hosted" +fi + +env | grep NETBIRD + envsubst < docker-compose.yml.tmpl > docker-compose.yml envsubst < management.json.tmpl > management.json envsubst < turnserver.conf.tmpl > turnserver.conf diff --git a/infrastructure_files/management.json.tmpl b/infrastructure_files/management.json.tmpl index 594954005..1f48bd11c 100644 --- a/infrastructure_files/management.json.tmpl +++ b/infrastructure_files/management.json.tmpl @@ -33,9 +33,20 @@ "AuthAudience": "$NETBIRD_AUTH_AUDIENCE", "AuthKeysLocation": "$NETBIRD_AUTH_JWT_CERTS", "CertFile":"$NETBIRD_MGMT_API_CERT_FILE", - "CertKey":"$NETBIRD_MGMT_API_CERT_KEY_FILE" + "CertKey":"$NETBIRD_MGMT_API_CERT_KEY_FILE", + "OIDCConfigEndpoint":"$NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT" }, "IdpManagerConfig": { "Manager": "none" - } + }, + "DeviceAuthorizationFlow": { + "Provider": "$NETBIRD_AUTH_DEVICE_AUTH_PROVIDER", + "ProviderConfig": { + "Audience": "$NETBIRD_AUTH_AUDIENCE", + "Domain": "$NETBIRD_AUTH0_DOMAIN", + "ClientID": "$NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID", + "TokenEndpoint": "$NETBIRD_AUTH_TOKEN_ENDPOINT", + "DeviceAuthEndpoint": "$NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT" + } + } } \ No newline at end of file diff --git a/infrastructure_files/setup.env.example b/infrastructure_files/setup.env.example index 8d4316c6e..a762c36ab 100644 --- a/infrastructure_files/setup.env.example +++ b/infrastructure_files/setup.env.example @@ -2,16 +2,14 @@ ## # Dashboard domain. e.g. app.mydomain.com NETBIRD_DOMAIN="" -# e.g. https://dev-24vkclam.us.auth0.com/ or https://YOUR-KEYCLOAK-HOST:8080/realms/netbird -NETBIRD_AUTH_AUTHORITY="" +# OIDC configuration e.g., https://example.eu.auth0.com/.well-known/openid-configuration +NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="" +NETBIRD_AUTH_AUDIENCE="" # e.g. netbird-client NETBIRD_AUTH_CLIENT_ID="" # indicates whether to use Auth0 or not: true or false NETBIRD_USE_AUTH0="false" -# a list of scopes supported e.g. `openid profile email offline_access api` for keycloak or `openid profile email offline_access api email_verified` for Auth0 -NETBIRD_AUTH_SUPPORTED_SCOPES="" -NETBIRD_AUTH_AUDIENCE="" -# URL of the JWT certificates e.g. https://dev-24vkclam.us.auth0.com/.well-known/jwks.json -NETBIRD_AUTH_JWT_CERTS="" +NETBIRD_AUTH_DEVICE_AUTH_PROVIDER="none" +NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID="" # e.g. hello@mydomain.com NETBIRD_LETSENCRYPT_EMAIL="" \ No newline at end of file diff --git a/infrastructure_files/tests/setup.env b/infrastructure_files/tests/setup.env index e7b3589e3..a6cfde9f4 100644 --- a/infrastructure_files/tests/setup.env +++ b/infrastructure_files/tests/setup.env @@ -3,15 +3,11 @@ # Dashboard domain. e.g. app.mydomain.com NETBIRD_DOMAIN="localhost" # e.g. https://dev-24vkclam.us.auth0.com/ or https://YOUR-KEYCLOAK-HOST:8080/realms/netbird -NETBIRD_AUTH_AUTHORITY=$CI_NETBIRD_AUTH_AUTHORITY +NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="https://example.eu.auth0.com/.well-known/openid-configuration" # e.g. netbird-client NETBIRD_AUTH_CLIENT_ID=$CI_NETBIRD_AUTH_CLIENT_ID # indicates whether to use Auth0 or not: true or false NETBIRD_USE_AUTH0=$CI_NETBIRD_USE_AUTH0 -# a list of scopes supported e.g. `openid profile email offline_access api` for keycloak or `openid profile email offline_access api email_verified` for Auth0 -NETBIRD_AUTH_SUPPORTED_SCOPES=$CI_NETBIRD_AUTH_SUPPORTED_SCOPES NETBIRD_AUTH_AUDIENCE=$CI_NETBIRD_AUTH_AUDIENCE -# URL of the JWT certificates e.g. https://dev-24vkclam.us.auth0.com/.well-known/jwks.json -NETBIRD_AUTH_JWT_CERTS=$CI_NETBIRD_AUTH_JWT_CERTS # e.g. hello@mydomain.com NETBIRD_LETSENCRYPT_EMAIL="" \ No newline at end of file diff --git a/management/cmd/management.go b/management/cmd/management.go index b83992fd4..977a0352b 100644 --- a/management/cmd/management.go +++ b/management/cmd/management.go @@ -324,7 +324,7 @@ func loadMgmtConfig(mgmtConfigPath string) (*server.Config, error) { oidcConfig.JwksURI, config.HttpConfig.AuthKeysLocation) config.HttpConfig.AuthKeysLocation = oidcConfig.JwksURI - if config.DeviceAuthorizationFlow != nil { + if !(config.DeviceAuthorizationFlow == nil || strings.ToLower(config.DeviceAuthorizationFlow.Provider) == string(server.NONE)) { log.Infof("overriding DeviceAuthorizationFlow.TokenEndpoint with a new value: %s, previously configured value: %s", oidcConfig.TokenEndpoint, config.DeviceAuthorizationFlow.ProviderConfig.TokenEndpoint) config.DeviceAuthorizationFlow.ProviderConfig.TokenEndpoint = oidcConfig.TokenEndpoint @@ -339,7 +339,6 @@ func loadMgmtConfig(mgmtConfigPath string) (*server.Config, error) { log.Infof("overriding DeviceAuthorizationFlow.ProviderConfig.Domain with a new value: %s, previously configured value: %s", u.Host, config.DeviceAuthorizationFlow.ProviderConfig.Domain) config.DeviceAuthorizationFlow.ProviderConfig.Domain = u.Host - } if config.IdpManagerConfig != nil { log.Infof("overriding Auth0ClientCredentials.AuthIssuer with a new value: %s, previously configured value: %s", diff --git a/management/server/config.go b/management/server/config.go index 8e2ffd995..bcdbad7e0 100644 --- a/management/server/config.go +++ b/management/server/config.go @@ -16,7 +16,7 @@ const ( TCP Protocol = "tcp" HTTP Protocol = "http" HTTPS Protocol = "https" - AUTH0 Provider = "auth0" + NONE Provider = "none" ) // Config of the Management service diff --git a/management/server/grpcserver.go b/management/server/grpcserver.go index b64909ea6..5b0ab12be 100644 --- a/management/server/grpcserver.go +++ b/management/server/grpcserver.go @@ -491,7 +491,7 @@ func (s *GRPCServer) GetDeviceAuthorizationFlow(ctx context.Context, req *proto. return nil, status.Error(codes.InvalidArgument, errMSG) } - if s.config.DeviceAuthorizationFlow == nil { + if s.config.DeviceAuthorizationFlow == nil || s.config.DeviceAuthorizationFlow.Provider == string(NONE) { return nil, status.Error(codes.NotFound, "no device authorization flow information available") }