Skip to content

Commit

Permalink
Add OAuth 2.0 Authentication tests (#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
sitingren authored Mar 30, 2023
1 parent 75fc59d commit b0e31ac
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 11 deletions.
78 changes: 71 additions & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ['1.19', '1.18', '1.17', '1.16', '1.15']
go-version: ['1.20', '1.19', '1.18', '1.17', '1.16']

steps:
- name: Check out repository
Expand All @@ -18,12 +18,23 @@ jobs:
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
- name: Set up a Vertica server

- name: Set up a Keycloak docker container
timeout-minutes: 5
run: |
docker network create -d bridge my-network
docker run -d -p 8080:8080 \
--name keycloak --network my-network \
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:21.0.1 start-dev
docker container ls
- name: Set up a Vertica server docker container
timeout-minutes: 15
run: |
docker run -d -p 5433:5433 -p 5444:5444 \
--name vertica_docker \
vertica/vertica-ce:12.0.2-0
--name vertica_docker --network my-network \
vertica/vertica-ce:12.0.3-0
echo "Vertica startup ..."
until docker exec vertica_docker test -f /data/vertica/VMart/agent_start.out; do \
echo "..."; \
Expand All @@ -36,10 +47,58 @@ jobs:
- name: Generating certs
run: |
./resources/tests/genCerts.sh
- name: Configure Keycloak
run: |
echo "Wait for keycloak ready ..."
bash -c 'while true; do curl -s localhost:8080 &>/dev/null; ret=$?; [[ $ret -eq 0 ]] && break; echo "..."; sleep 3; done'
REALM="test"
USER="oauth_user"
PASSWORD="password"
CLIENT_ID="vertica"
CLIENT_SECRET="P9f8350QQIUhFfK1GF5sMhq4Dm3P6Sbs"
docker exec -i keycloak /bin/bash <<EOF
/opt/keycloak/bin/kcadm.sh config credentials --server http://localhost:8080 --realm master --user admin --password admin
/opt/keycloak/bin/kcadm.sh create realms -s realm=${REALM} -s enabled=true
/opt/keycloak/bin/kcadm.sh update realms/${REALM} -s accessTokenLifespan=3600
/opt/keycloak/bin/kcadm.sh get realms/${REALM}
/opt/keycloak/bin/kcadm.sh create users -r ${REALM} -s username=${USER} -s enabled=true
/opt/keycloak/bin/kcadm.sh set-password -r ${REALM} --username ${USER} --new-password ${PASSWORD}
/opt/keycloak/bin/kcadm.sh get users -r ${REALM}
/opt/keycloak/bin/kcadm.sh create clients -r ${REALM} -s clientId=${CLIENT_ID} -s enabled=true \
-s 'redirectUris=["/*"]' -s 'webOrigins=["/*"]' -s secret=${CLIENT_SECRET} -s directAccessGrantsEnabled=true -o
EOF
# Retrieving an Access Token
curl --location --request POST http://`hostname`:8080/realms/${REALM}/protocol/openid-connect/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "username=${USER}" \
--data-urlencode "password=${PASSWORD}" \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode "client_secret=${CLIENT_SECRET}" \
--data-urlencode 'grant_type=password' -o oauth.json
cat oauth.json | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["access_token"])' > access_token.txt
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "CREATE AUTHENTICATION v_oauth METHOD 'oauth' HOST '0.0.0.0/0';"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_oauth SET client_id = '${CLIENT_ID}';"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_oauth SET client_secret = '${CLIENT_SECRET}';"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_oauth SET discovery_url = 'http://`hostname`:8080/realms/${REALM}/.well-known/openid-configuration';"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_oauth SET introspect_url = 'http://`hostname`:8080/realms/${REALM}/protocol/openid-connect/token/introspect';"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "SELECT * FROM client_auth WHERE auth_name='v_oauth';"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "CREATE USER ${USER};"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "GRANT AUTHENTICATION v_oauth TO ${USER};"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "GRANT ALL ON SCHEMA PUBLIC TO ${USER};"
# A dbadmin-specific authentication record (connect remotely) is needed after setting up an OAuth user
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "CREATE AUTHENTICATION v_dbadmin_hash METHOD 'hash' HOST '0.0.0.0/0';"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "ALTER AUTHENTICATION v_dbadmin_hash PRIORITY 10000;"
docker exec -u dbadmin vertica_docker /opt/vertica/bin/vsql -c "GRANT AUTHENTICATION v_dbadmin_hash TO dbadmin;"
- name: Run tests without TLS
run: |
go test -race . -args --locator localhost:5433 --user dbadmin
export VERTICA_TEST_OAUTH_ACCESS_TOKEN=`cat access_token.txt`
go test -v -race . -args --locator localhost:5433 --user dbadmin
go test -race . -args --locator localhost:5433 --user dbadmin --use_prepared_statements=0
go test -race ./logger
Expand All @@ -52,7 +111,8 @@ jobs:
- name: Testing with --tlsmode=server
run: |
go test -race . -args --locator localhost:5433 --user dbadmin --tlsmode=server
export VERTICA_TEST_OAUTH_ACCESS_TOKEN=`cat access_token.txt`
go test -v -race . -args --locator localhost:5433 --user dbadmin --tlsmode=server
go test -race . -args --locator localhost:5433 --user dbadmin --tlsmode=server --use_prepared_statements=0
- name: Setting SSLCa in the database
Expand All @@ -61,5 +121,9 @@ jobs:
- name: Testing with --tlsmode=custom
run: |
go test -race . -args --locator localhost:5433 --user dbadmin --tlsmode=custom
export VERTICA_TEST_OAUTH_ACCESS_TOKEN=`cat access_token.txt`
go test -v -race . -args --locator localhost:5433 --user dbadmin --tlsmode=custom
go test -race . -args --locator localhost:5433 --user dbadmin --tlsmode=custom --use_prepared_statements=0

6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ were args are one of the following:
| | | 'server-strict' = server must support SSL |
| locator | host and port of the Vertica connection | (default) localhost:5433
| user | Vertica user ID | (default) the userid of the running user |
| password | Vertica password for the connecting user | (default) (empty)
|
| password | Vertica password for the connecting user | (default) (empty) |
| oauth_access_token | the OAuth Access Token to connect to Vertica, only used for OAuth Authentication tests | (default) (empty) |

**NOTE:** Since it's often a bad idea to put your password on the command line, you can set the VERTICA_TEST_PASSWORD environment variable. Even if environment variable is set, the "--password" flag will supercede it.
**NOTE:** Since it's often a bad idea to put your password on the command line, you can set the VERTICA_TEST_PASSWORD environment variable. Even if environment variable is set, the "--password" flag will supercede it. Similarly, you can set the VERTICA_TEST_OAUTH_ACCESS_TOKEN environment variable instead of "--oauth_access_token" flag.

For example:

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ vertica-sql-go is a native Go adapter for the Vertica (http://www.vertica.com) d

Please check out [release notes](https://github.com/vertica/vertica-sql-go/releases) to learn about the latest improvements.

vertica-sql-go has been tested with Vertica 12.0.2 and Go 1.15/1.16/1.17/1.18/1.19.
vertica-sql-go has been tested with Vertica 12.0.3 and Go 1.16/1.17/1.18/1.19/1.20.

## Installation

Expand Down
26 changes: 26 additions & 0 deletions driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ var (
otherConnectString string
badConnectString string
failoverConnectString string
oauthConnectString string
ctx context.Context
)

Expand Down Expand Up @@ -164,6 +165,29 @@ func closeConnection(t *testing.T, connDB *sql.DB, teardownScript ...interface{}
assertNoErr(t, connDB.Close())
}

func TestOAuthConnection(t *testing.T) {
if len(*oauthAccessToken) == 0 {
t.Skip("OAUTH Access Token is not provided, test skipped")
return
}

// Let the oauth user try to login now.
connDB, err := sql.Open("vertica", oauthConnectString)
defer closeConnection(t, connDB)
assertNoErr(t, err)
assertNoErr(t, connDB.PingContext(ctx))

rows, err := connDB.QueryContext(ctx, "SELECT authentication_method FROM sessions WHERE session_id=(SELECT current_session())")
assertNoErr(t, err)
defer rows.Close()

var authMethod string
for rows.Next() {
assertNoErr(t, rows.Scan(&authMethod))
assertEqual(t, authMethod, "OAuth")
}
}

func TestTLSConfiguration(t *testing.T) {
connDB := openConnection(t)
defer closeConnection(t, connDB)
Expand Down Expand Up @@ -1165,6 +1189,7 @@ var verticaPassword = flag.String("password", os.Getenv("VERTICA_TEST_PASSWORD")
var verticaHostPort = flag.String("locator", "localhost:5433", "Vertica's host and port")
var tlsMode = flag.String("tlsmode", "none", "SSL/TLS mode (none, server, server-strict, custom)")
var usePreparedStmts = flag.Bool("use_prepared_statements", true, "whether to use prepared statements for all queries/executes")
var oauthAccessToken = flag.String("oauth_access_token", os.Getenv("VERTICA_TEST_OAUTH_ACCESS_TOKEN"), "the OAuth Access Token to connect to Vertica")

const (
keyPath string = "resources/tests/ssl/client.key"
Expand Down Expand Up @@ -1246,6 +1271,7 @@ func init() {
otherConnectString = "vertica://TestGuy:TestGuyPass@" + *verticaHostPort + "/?tlsmode=" + *tlsMode
badConnectString = "vertica://TestGuy:TestGuyBadPass@" + *verticaHostPort + "/?tlsmode=" + *tlsMode
failoverConnectString = "vertica://" + *verticaUserName + ":" + *verticaPassword + "@badHost" + "?backup_server_node=abc.com:100000," + *verticaHostPort + ",localhost:port"
oauthConnectString = "vertica://" + *verticaUserName + "@" + *verticaHostPort + "/?oauth_access_token=" + *oauthAccessToken + "&tlsmode=" + *tlsMode

ctx = context.Background()
}

0 comments on commit b0e31ac

Please sign in to comment.