strip newline before Base64 decoding (#916)
This commit is contained in:
committed by
Joe Nelson
parent
968bf9ce59
commit
7fcdbf9153
@@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- #877, Base64 secret read from a file ending with a newline - @eric-brechemier
|
||||||
- #896, Boolean env var interpolation in config file - @begriffs
|
- #896, Boolean env var interpolation in config file - @begriffs
|
||||||
|
|
||||||
## [0.4.2.0] - 2017-06-11
|
## [0.4.2.0] - 2017-06-11
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ dependencies:
|
|||||||
test:
|
test:
|
||||||
override:
|
override:
|
||||||
- POSTGREST_TEST_CONNECTION=$(test/create_test_db "postgres://ubuntu@localhost" postgrest_test) stack test
|
- POSTGREST_TEST_CONNECTION=$(test/create_test_db "postgres://ubuntu@localhost" postgrest_test) stack test
|
||||||
|
- test/io-tests.sh
|
||||||
- git ls-files | grep '\.l\?hs$' | xargs stack exec -- hlint -X QuasiQuotes -X NoPatternSynonyms "$@"
|
- git ls-files | grep '\.l\?hs$' | xargs stack exec -- hlint -X QuasiQuotes -X NoPatternSynonyms "$@"
|
||||||
- stack exec -- cabal update
|
- stack exec -- cabal update
|
||||||
- stack exec --no-ghc-package-path -- cabal install --only-d --dry-run
|
- stack exec --no-ghc-package-path -- cabal install --only-d --dry-run
|
||||||
|
|||||||
+2
-2
@@ -22,7 +22,7 @@ import Data.ByteString.Base64 (decode)
|
|||||||
import Data.IORef (IORef, atomicWriteIORef,
|
import Data.IORef (IORef, atomicWriteIORef,
|
||||||
newIORef, readIORef)
|
newIORef, readIORef)
|
||||||
import Data.String (IsString (..))
|
import Data.String (IsString (..))
|
||||||
import Data.Text (pack, replace, stripPrefix)
|
import Data.Text (pack, replace, stripPrefix, strip)
|
||||||
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
|
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
|
||||||
import Data.Text.IO (hPutStrLn, readFile)
|
import Data.Text.IO (hPutStrLn, readFile)
|
||||||
import Data.Time.Clock.POSIX (getPOSIXTime)
|
import Data.Time.Clock.POSIX (getPOSIXTime)
|
||||||
@@ -278,7 +278,7 @@ loadSecretFile conf = extractAndTransform mSecret
|
|||||||
transformString :: Bool -> Text -> IO ByteString
|
transformString :: Bool -> Text -> IO ByteString
|
||||||
transformString False t = return . encodeUtf8 $ t
|
transformString False t = return . encodeUtf8 $ t
|
||||||
transformString True t =
|
transformString True t =
|
||||||
case decode (encodeUtf8 $ replaceUrlChars t) of
|
case decode (encodeUtf8 $ strip $ replaceUrlChars t) of
|
||||||
Left errMsg -> panic $ pack errMsg
|
Left errMsg -> panic $ pack errMsg
|
||||||
Right bs -> return bs
|
Right bs -> return bs
|
||||||
setSecret bs = conf {configJwtSecret = Just bs}
|
setSecret bs = conf {configJwtSecret = Just bs}
|
||||||
|
|||||||
Executable
+111
@@ -0,0 +1,111 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Run unit tests for Input/Ouput of PostgREST seen as a black box
|
||||||
|
# with test output in Test Anything Protocol format.
|
||||||
|
#
|
||||||
|
# References:
|
||||||
|
# [1] Test Anything Protocol
|
||||||
|
# https://testanything.org/
|
||||||
|
#
|
||||||
|
# [2] TAP Specification
|
||||||
|
# https://testanything.org/tap-specification.html
|
||||||
|
#
|
||||||
|
# [3] List of TCP and UDP port numbers
|
||||||
|
# https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
|
||||||
|
#
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
cd io-tests
|
||||||
|
|
||||||
|
# Port for Test PostgREST Server (must match config)
|
||||||
|
pgrPort=49421 # in range 49152–65535: for private or temporary use
|
||||||
|
|
||||||
|
# TAP utilities
|
||||||
|
currentTest=1
|
||||||
|
failedTests=0
|
||||||
|
bailOut(){ echo "Bail out! $1"; exit 1; }
|
||||||
|
result(){ echo "$1 $currentTest $2"; currentTest=$(( $currentTest + 1 )); }
|
||||||
|
todo(){ result 'ok' "# TODO: $*"; }
|
||||||
|
skip(){ result 'ok' "# SKIP: $*"; }
|
||||||
|
ok(){ result 'ok' "- $1"; }
|
||||||
|
ko(){ result 'not ok' "- $1"; failedTests=$(( $failedTests + 1 )); }
|
||||||
|
comment(){ echo "# $1"; }
|
||||||
|
|
||||||
|
# Utilities to start/stop test PostgREST server running in the background
|
||||||
|
pgrStart(){ stack exec -- postgrest "$1" >/dev/null & pgrPID="$!"; }
|
||||||
|
pgrStartRead(){ stack exec -- postgrest "$1" >/dev/null < "$2" & pgrPID="$!"; }
|
||||||
|
pgrStarted(){ kill -0 "$pgrPID" 2>/dev/null; }
|
||||||
|
pgrStop(){ kill "$pgrPID" 2>/dev/null; }
|
||||||
|
pgrStopAll(){ pkill -f "$(stack path --local-install-root)/bin/postgrest"; }
|
||||||
|
|
||||||
|
# Utilities to send HTTP requests to the PostgREST server
|
||||||
|
rootStatus(){
|
||||||
|
curl -s -o /dev/null -w '%{http_code}' "http://localhost:$pgrPort/"
|
||||||
|
}
|
||||||
|
authorsStatus(){
|
||||||
|
curl -s -o /dev/null -w '%{http_code}' \
|
||||||
|
-H "Authorization: Bearer $( cat "$1" )" \
|
||||||
|
"http://localhost:$pgrPort/authors_only"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start and End of Unit Tests
|
||||||
|
setUp(){ pgrStopAll; }
|
||||||
|
cleanUp(){ pgrStopAll; }
|
||||||
|
|
||||||
|
# Unit Test Templates
|
||||||
|
readSecretFromFile(){
|
||||||
|
case "$1" in
|
||||||
|
*.b64)
|
||||||
|
pgrConfig="base64-secret-from-file.config";;
|
||||||
|
*)
|
||||||
|
pgrConfig="secret-from-file.config";;
|
||||||
|
esac
|
||||||
|
pgrStartRead "./configs/$pgrConfig" "./secrets/$1"
|
||||||
|
while pgrStarted && test "$( rootStatus )" -ne 200
|
||||||
|
do
|
||||||
|
# wait for the server to start
|
||||||
|
sleep 0.1 \
|
||||||
|
|| sleep 1 # fallback: subsecond sleep is not standard and may fail
|
||||||
|
done
|
||||||
|
if pgrStarted
|
||||||
|
then
|
||||||
|
authorsJwt="./secrets/${1%.*}.jwt"
|
||||||
|
httpStatus="$( authorsStatus "$authorsJwt" )"
|
||||||
|
if test "$httpStatus" -eq 200
|
||||||
|
then
|
||||||
|
ok "authentication with $2 secret read from a file"
|
||||||
|
else
|
||||||
|
ko "failed to authenticate using JWT for $2 secret: $httpStatus"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
ko "failed to read $2 secret from a file"
|
||||||
|
fi
|
||||||
|
pgrStop
|
||||||
|
}
|
||||||
|
|
||||||
|
# PRE: curl must be available
|
||||||
|
test -n "$(command -v curl)" || bailOut 'curl is not available'
|
||||||
|
|
||||||
|
# PRE: postgres must be running
|
||||||
|
psql -l 1>/dev/null 2>/dev/null || bailOut 'postgres is not running'
|
||||||
|
|
||||||
|
setUp
|
||||||
|
|
||||||
|
totalTests=12
|
||||||
|
echo "1..$totalTests"
|
||||||
|
|
||||||
|
readSecretFromFile word.noeol 'simple (no EOL)'
|
||||||
|
skip readSecretFromFile word.txt 'simple'
|
||||||
|
readSecretFromFile ascii.noeol 'ASCII (no EOL)'
|
||||||
|
skip readSecretFromFile ascii.txt 'ASCII'
|
||||||
|
readSecretFromFile utf8.noeol 'UTF-8 (no EOL)'
|
||||||
|
skip readSecretFromFile utf8.txt 'UTF-8'
|
||||||
|
skip readSecretFromFile binary.noeol 'binary'
|
||||||
|
skip readSecretFromFile binary.eol 'binary (+EOL)'
|
||||||
|
|
||||||
|
readSecretFromFile word.b64 'Base64 (simple)'
|
||||||
|
readSecretFromFile ascii.b64 'Base64 (ASCII)'
|
||||||
|
readSecretFromFile utf8.b64 'Base64 (UTF-8)'
|
||||||
|
readSecretFromFile binary.b64 'Base64 (binary)'
|
||||||
|
|
||||||
|
cleanUp
|
||||||
|
|
||||||
|
exit $failedTests
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
db-uri = "postgres:///postgrest_test"
|
||||||
|
db-schema = "test"
|
||||||
|
db-anon-role = "postgrest_test_anonymous"
|
||||||
|
db-pool = 1
|
||||||
|
server-host = "*4"
|
||||||
|
server-port = 49421
|
||||||
|
|
||||||
|
# Read secret from a file: /dev/stdin (alias for standard input)
|
||||||
|
jwt-secret = "@/dev/stdin"
|
||||||
|
secret-is-base64 = true
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
db-uri = "postgres:///postgrest_test"
|
||||||
|
db-schema = "test"
|
||||||
|
db-anon-role = "postgrest_test_anonymous"
|
||||||
|
db-pool = 1
|
||||||
|
server-host = "*4"
|
||||||
|
server-port = 49421
|
||||||
|
|
||||||
|
# Read secret from a file: /dev/stdin (alias for standard input)
|
||||||
|
jwt-secret = "@/dev/stdin"
|
||||||
|
secret-is-base64 = false
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
QSBCIEMKSXQncyBlYXN5IGFzLCAxIDIgMw==
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.MsR2A5HkhQdBsuQhXH8TvUdlvezBm5JEu4SOmHj34KI
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
A B C
|
||||||
|
It's easy as, 1 2 3
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
A B C
|
||||||
|
It's easy as, 1 2 3
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
i6aWVaZ4Zt8=
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
協剖ヲxf゚
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.ySt_r_BN596NjZGcUAnlMAflDARDjrsR2c-fkOWlbFs
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
協剖ヲxf゚
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
4pqg77iPIOKaoO+4jiBVbmljb2RlIOKYoO+4jyDimKA=
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.VFfaoJohnDeJMA-awM6Y7blbOjXDNwmtx48Z-0bIKrE
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
⚠️ ⚠︎ Unicode ☠️ ☠
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
⚠️ ⚠︎ Unicode ☠️ ☠
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
QUJDMTIz
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.yERzinJhzJ5XYKZuxVroqsAwGXMtCxntfm8HVxc1amI
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ABC123
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ABC123
|
||||||
Reference in New Issue
Block a user