diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..0e94ef78 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: go + +go: + - 1.4 + - 1.5 + +sudo: false + +install: + - echo $PWD + - cd $GOPATH/src/github.com/kwk/docker_auth/auth_server + - go get + - go install github.com/kwk/docker_auth/auth_server + +script: + - echo $PWD + - go test -v ./... + - cd test/ && ./test-static-acl.sh diff --git a/README.md b/README.md index c36b6002..8d5da947 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://travis-ci.org/kwk/docker_auth.svg?branch=test-for-auth-server)](https://travis-ci.org/kwk/docker_auth) + Docker Registry 2.0 authentication server ========================================= diff --git a/auth_server/.gitignore b/auth_server/.gitignore deleted file mode 100644 index 24443656..00000000 --- a/auth_server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -auth_server diff --git a/auth_server/test/certs/README.md b/auth_server/test/certs/README.md new file mode 100644 index 00000000..321bb1cf --- /dev/null +++ b/auth_server/test/certs/README.md @@ -0,0 +1,34 @@ +# Creation of example certificates + +# Certificate and key for the auth server + +The `auth.crt` and `auth.key` files have been created using this command: + +``` +openssl req -newkey rsa:4096 -nodes -sha256 -keyout auth.key -x509 -days 365 -out auth.crt +Generating a 4096 bit RSA private key +................................................................................................................................................................................................................++ +........................................................................++ +writing new private key to 'auth.key' +----- +You are about to be asked to enter information that will be incorporated +into your certificate request. +What you are about to enter is what is called a Distinguished Name or a DN. +There are quite a few fields but you can leave some blank +For some fields there will be a default value, +If you enter '.', the field will be left blank. +----- +Country Name (2 letter code) [AU]:DE +State or Province Name (full name) [Some-State]:Example State +Locality Name (eg, city) []:Example City +Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Company +Organizational Unit Name (eg, section) []:Example Organizational Unit +Common Name (e.g. server FQDN or YOUR name) []:auth.example.com +Email Address []:admin@auth.example.com +``` + +# How to list the contents of one of the certificates + +```bash +openssl x509 -in auth.crt -text +``` diff --git a/auth_server/test/certs/auth.crt b/auth_server/test/certs/auth.crt new file mode 100644 index 00000000..84b5d7ae --- /dev/null +++ b/auth_server/test/certs/auth.crt @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +MIIGUTCCBDmgAwIBAgIJAIg5BM++T0GHMA0GCSqGSIb3DQEBCwUAMIG+MQswCQYD +VQQGEwJERTEWMBQGA1UECAwNRXhhbXBsZSBTdGF0ZTEVMBMGA1UEBwwMRXhhbXBs +ZSBDaXR5MRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxJDAiBgNVBAsMG0V4YW1w +bGUgT3JnYW5pemF0aW9uYWwgVW5pdDEZMBcGA1UEAwwQYXV0aC5leGFtcGxlLmNv +bTElMCMGCSqGSIb3DQEJARYWYWRtaW5AYXV0aC5leGFtcGxlLmNvbTAeFw0xNTEw +MjYxMTAzNDhaFw0xNjEwMjUxMTAzNDhaMIG+MQswCQYDVQQGEwJERTEWMBQGA1UE +CAwNRXhhbXBsZSBTdGF0ZTEVMBMGA1UEBwwMRXhhbXBsZSBDaXR5MRgwFgYDVQQK +DA9FeGFtcGxlIENvbXBhbnkxJDAiBgNVBAsMG0V4YW1wbGUgT3JnYW5pemF0aW9u +YWwgVW5pdDEZMBcGA1UEAwwQYXV0aC5leGFtcGxlLmNvbTElMCMGCSqGSIb3DQEJ +ARYWYWRtaW5AYXV0aC5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBANv6wuZ8U9iW8/+RFZOwNC5mrjWdQcAGHHTebrOj0PZDfyDSbOQ6 +N+/B06dKgkJe70hDXrKqQV2ABnopJjFumqJAcczVfOEcT7dQJYcRav5OGxPl6c5m +5KyBMoyFfkclrSrt553ZqbJ90rzbdkXSWobSwZ7y2zORtS91lArRwf4K4ZJWjLC0 +1WUwcpXOeuez+vymhwi4c3d0RT48HLZhdy3t+S3ANE3B0jqwMsWvkfUp3uO8kOHo +ruc1XWdChxj+LfsrNsoQk11iy2OBMmk55usFQbikBRvuNvvWCSmyh5SllOEyM017 +E+qqkdEE/bo68EvqLurgzo0BnsW9YaQWblr8Qg38V6pR5ny2WJdW+rI/0cqmSP1r +uOLd0JvrJIUhV1CV1EpJotlgpmxSNMWuxT8T1aWkd4LSt6VHYxySV76CcQ5BkuQ0 +JFg3ynfT+M39hniXmA+XTqAb9fg13aBtnJ7wBb5+PzxxDnsGdVtefbVQdIyo/W5V +EK7XRRk3cfrH+0TNI73r4eRN+n4rYwQXiEiT86KIull+XrDVaW4noC6hxDZQuzay +42CcVnpDdnU1FPby6+GgKBzKrXrvq6jXtuOOMEOToXpjbsE2kyGiGPofcksRhEQv +bwlV8mpBB8zoHWekSMOc59KsUtk9tz7Ud6c3B+mjOEozx/7HJhYIfH4HAgMBAAGj +UDBOMB0GA1UdDgQWBBTbQYvhJfcSfEl2FC+JweoZs5KtiTAfBgNVHSMEGDAWgBTb +QYvhJfcSfEl2FC+JweoZs5KtiTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA +A4ICAQC6IOLZW7rnHt1vgyUsxVcNrJZvQmWyctOyMfMYGsB5OC/LUtwOJWHc1B9v +RCwdnsZi1/TGDQrgfnE5TgROb4ysbOtPNtk9VeDS1OoJuunK8WZl2xgjyscs24Id +jJOrgMHvNvAtEIfmcjnBuqInpysh+fP3eJgcO/61iVU0bxilkeN2zRhnWGr9mIi4 +IOyOh3q5tmF/6nHncgrkg1qlozzXIEcJw5X/IKcOJWJlDwWse4lXj3fjK8SvPxz6 +JNuLgoVtcT75ZbjHzRrY3n6m2jj+LFuclDs1tLRImMvGrtNleW5ZwUgnMK8367hH +r7GpnVAnnSuKQz7n7efHnHXNet0fakT/4Ie9IbLnvREefBeYNA+P/ugi5MWKIJuR +ALQASAcq/wiMnZ0aWUj2qN5KLM0u+9tRe+GPHF9+ii9McIo+kcPH0opZCLUIx8uw +MwNoaA11xu21+kLgyvMGk2InDgazjiyDSuNbGx9mUH0cGttl+4VtmmMQMkZ0uhf9 +fKQb9Fyen+yXPRdrtW+atfnIHa8IM7pm36yQ926JM4cEroqYplXSkOfx9mjEzKWv +YlfEbz3AHB/QG0Kq5lMSOw7fPgNS2iwnwKPwDh0qvyQTIfA/pPQ6qPmr5OOO1+PT +QrWHAjG3qbI3vgzDab32kwevjChelqmfoQyqT0wMypMYmD2L6Q== +-----END CERTIFICATE----- diff --git a/auth_server/test/certs/auth.key b/auth_server/test/certs/auth.key new file mode 100644 index 00000000..87ca4850 --- /dev/null +++ b/auth_server/test/certs/auth.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +my7FsXDuRNUL8epD5iO7hhddN53Yig== +-----END PRIVATE KEY----- diff --git a/auth_server/test/common.sh b/auth_server/test/common.sh new file mode 100755 index 00000000..a3c09a4d --- /dev/null +++ b/auth_server/test/common.sh @@ -0,0 +1,151 @@ +#!/bin/bash + +# Outputs everything to stderr with a UTC datetime prefixed in braces "[]" +log() { + echo "[$(date -u)] $@" 1>&2 +} + +# Outputs everything to stderr +logtest() { + echo -e "$@" 1>&2 +} + +# Prints a summary of passed and failed tests and shows where to find the logs. +# Then the server is stopped. +cleanup() { + EXITCODE=0 + if [ "$NUMERRORS" != "0" ]; then + log "$NUMERRORS of $NUMTESTS tests were failing:" + echo "" 1>&2 + echo "----------------------------------------------------------------" 1>&2 + cat $FAILEDTESTS 1>&2 + echo "----------------------------------------------------------------" 1>&2 + echo "" 1>&2 + EXITCODE=1 + else + log "All $NUMTESTS tests were passing!" + fi + log "Logs are in $LOGDIR" + log "Shutting down $PROGNAME" + # Shutdown auth_server process if it is still running + killall $PROGNAME + cd $OLDPWD + exit $EXITCODE +} + +# Encode to Base64-URL without padding. +function base64UrlEncode { + echo -n "$1" | openssl enc -a -A | tr -d '=' | tr '/+' '_-' +} + +# Decode from Base64-URL without padding. +function base64UrlDecode { + _l=$((${#1} % 4)) + if [ $_l -eq 2 ]; then _s="$1"'==' + elif [ $_l -eq 3 ]; then _s="$1"'=' + else _s="$1" ; fi + echo "$_s" | tr '_-' '/+' | openssl enc -d -a -A +} + + +# Sets up some paths and variables and builds or reuses the auth_server artifact. +# The first argument must be the path to the config file to be used by the +# auth_server. +setuptest() { + if [ "$#" != "1" ]; then + log "You must specify a config file for the auth_server." + exit 2 + fi + + trap "cleanup" EXIT + THISDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # directory of this script + PROGNAME=auth_server + OLDPWD=$PWD + LOGDIR=$(mktemp -d) + NUMERRORS=0 + NUMTESTS=0 + FAILEDTESTS=$LOGDIR/failed_tests.txt + CONFIGFILE=$1 + PUBKEYFILE=$LOGDIR/pubkey.pem + + log "Extract public key from certificate once" + openssl x509 -pubkey -noout -in $TESTDIR/certs/auth.crt > $PUBKEYFILE + + # If the ENV_NOCOLOR environment variable is set, don't output colorful reports. + set +u + if [ -z "$ENV_NOCOLOR" ]; then + COLOR_ERROR='\033[0;31m' # Red + COLOR_SUCCESS='\033[0;32m' # Green + COLOR_NONE='\033[0m' # No Color + else + COLOR_ERROR='' + COLOR_SUCCESS='' + COLOR_NONE='' # No Color + fi + set -u + + # Build the auth_server or reuse an existing artifact + cd $TESTDIR/.. + if [ ! -e "$PROGNAME" ]; then + log "Building $PROGNAME" + go build + else + log "Found already existing $PROGNAME (skipping build)." + fi +} + +# Starts the auth_server and fires an authorization requests to it to see if it +# is responding correctly. Then, the server is shutdown. +# +# The inputs are: +# +# 1. Expected Result Code (e.g. "200", or "401") +# 2. The auth Header with which to authenticate, e.g. "Authorization: Basic $(echo -n "test:123" | base64)" +# 3. The URL to try, e.g. "https://localhost:5001/auth?service=registry.docker.io&scope=repository:somenamespace/somerepo,pull,push" +# 4. A message to describe the test. +testAuth() { + expectedResponseCode=$1 + authHeader="$2" + URL="$3" + msg=$4 + + NUMTESTS=$((NUMTESTS+1)) + LOGFILE=$LOGDIR/$PROGNAME.log.$NUMTESTS + OUTFILE=$LOGDIR/$PROGNAME.out.$NUMTESTS + + # Start the auth server + ./$PROGNAME -v 5 -alsologtostderr=true $CONFIGFILE > $LOGFILE 2>&1 & #-log_dir=$LOGDIR + sleep 2 + + FAILED=0 + + respCode=$(curl -sk --output "$OUTFILE" --write-out '%{http_code}' -H "$authHeader" "$URL") + if [ "$respCode" != "$expectedResponseCode" ]; then + FAILED=1 + else + # Analyse the token we received + + TOKEN=$(cat $OUTFILE | jq ".token" | tr -d '"') + HEADER=$(base64UrlDecode $(echo $TOKEN | cut -d '.' -f 1)) + PAYLOAD=$(base64UrlDecode $(echo $TOKEN | tr -d '"' | cut -d '.' -f 2)) + SIGNATURE=$(base64UrlDecode $(echo $TOKEN | tr -d '"' | cut -d '.' -f 3)) + + # Verify the signature + # TODO (kwk) Either implement in bash or switch to Go and docker/libtrust instead + fi + + if [ "$FAILED" == "1" ]; then + echo -e "${COLOR_ERROR}TEST FAILED: $msg${COLOR_NONE}" | tee --append $FAILEDTESTS 1>&2 + echo -e " - Expected $expectedResponseCode and got \"$respCode\" with authHeader=\"$authHeader\" and URL=\"$URL\"" 1>&2 + echo -e "------------------------- LOG ------------------------------" 1>&2 + cat $LOGFILE + echo -e "----------------------------------------------------------------" 1>&2 + #cat $LOGDIR/$PROGNAME.* 1>&2 + NUMERRORS=$((NUMERRORS+1)) + #exit 2 + else + logtest "${COLOR_SUCCESS}TEST PASSED: $msg${COLOR_NONE}" + fi + + killall $PROGNAME +} diff --git a/auth_server/test/config/static-acls.yml b/auth_server/test/config/static-acls.yml new file mode 100644 index 00000000..697f0b73 --- /dev/null +++ b/auth_server/test/config/static-acls.yml @@ -0,0 +1,65 @@ +# See reference.yml for explanation for explanation of all options. + +server: + addr: ":5001" + certificate: "test/certs/auth.crt" + key: "test/certs/auth.key" + +token: + issuer: "Acme auth server" # Must match issuer in the Registry config. + expiration: 900 + +users: + # Password is specified as a BCrypt hash. Use htpasswd -B to generate. + "admin": + password: "$2y$05$LO.vzwpWC5LZGqThvEfznu8qhb5SGqvBSWY1J3yZ4AxtMRZ3kN5jC" # badmin + "test": + password: "$2y$05$WuwBasGDAgr.QCbGIjKJaep4dhxeai9gNZdmBnQXqpKly57oNutya" # 123 + "test1": + password: "$2y$05$WuwBasGDAgr.QCbGIjKJaep4dhxeai9gNZdmBnQXqpKly57oNutya" # 123 + "test2": + password: "$2y$05$WuwBasGDAgr.QCbGIjKJaep4dhxeai9gNZdmBnQXqpKly57oNutya" # 123 + +# ACL specifies who can do what. If the match section of an entry matches the +# request, the set of allowed actions will be applied to the token request +# and a ticket will be issued only for those of the requested actions that are +# allowed by the rule. +# * It is possible to match on user's name ("account"), subject type ("type") +# and name ("name"; for type=repository which, at the timeof writing, is the +# only known subject type, this is the image name). +# * Matches are evaluated as shell file name patterns ("globs") by default, +# so "foobar", "f??bar", "f*bar" are all valid. For even more flexibility +# match patterns can be evaluated as regexes by enclosing them in //, e.g. +# "/(foo|bar)/". +# * ACL is evaluated in the order it is defined until a match is found. +# * Empty match clause matches anything, it only makes sense at the end of the +# list and can be used as a way of specifying default permissions. +# * Empty actions set means "deny everything". Thus, a rule with `actions: []` +# is in effect a "deny" rule. +# * A special set consisting of a single "*" action means "allow everything". +# * If no match is found the default is to deny the request. +# +# You can use the following variables from the ticket request in any field: +# * ${account} - the account name, currently the same as authenticated user's name. +# * ${service} - the service name, specified by auth.token.service in the registry config. +# * ${type} - the type of the entity, normally "repository". +# * ${name} - the name of the repository (i.e. image), e.g. centos. +acl: + # Admin has full access to everything. + - match: {account: "admin"} + actions: ["*"] + # User "test" has full access to test-* images but nothing else. + - match: {account: "test", name: "test-*"} + actions: ["*"] + - match: {account: "test"} + actions: [] + # All logged in users can pull all images. + - match: {account: "/.+/"} + actions: ["pull"] + # All logged in users can push all images that are in a namespace beginning with their name + - match: {account: "/.+/", name: "${account}/*"} + actions: ["*"] + # Anonymous users can pull "hello-world". + - match: {account: "", name: "hello-world"} + actions: ["pull"] + # Access is denied by default. diff --git a/auth_server/test/test-static-acl.sh b/auth_server/test/test-static-acl.sh new file mode 100755 index 00000000..a1f065c2 --- /dev/null +++ b/auth_server/test/test-static-acl.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Exit on error and unitialized variables +set -eu + +TESTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # directory of this script + +# Load in functions shared by multiple tests +source $TESTDIR/common.sh +setuptest test/config/static-acls.yml + +# Configure Basic auth authorization headers +adminAuthHeader="Authorization: Basic $(echo -n "admin:badmin" | base64)" +testAuthHeader="Authorization: Basic $(echo -n "test:123" | base64)" +test1AuthHeader="Authorization: Basic $(echo -n "test1:123" | base64)" +test2AuthHeader="Authorization: Basic $(echo -n "test2:123" | base64)" + +# The auth_server will be running on port 5001 as defined in the test/config/static-acls.yml +baseUrl="https://localhost:5001/auth?service=registry.docker.io&scope=repository:" + +log "Starting tests" + +# Admin has full access to everything. +testAuth "200" "$adminAuthHeader" "${baseUrl}randomuser/randomrepo:pull,push" 'Admin has full access to everything.' + +# User "test" has full access to test-* images but nothing else. +testAuth "200" "$testAuthHeader" "${baseUrl}test-randomuser/randomrepo:pull" 'User "test" has full access to test-* images but nothing else. (1)' +testAuth "200" "$testAuthHeader" "${baseUrl}randomuser/test-randomrepo:pull,push" 'User "test" has full access to test-* images but nothing else. (2)' +testAuth "200" "$testAuthHeader" "${baseUrl}randomuser/randomrepo:push" 'User "test" has full access to test-* images but nothing else. (3)' +testAuth "200" "$testAuthHeader" "${baseUrl}randomuser/randomrepo:pull" 'User "test" has full access to test-* images but nothing else. (4)' + +# All logged in users can pull all images. +testAuth "200" "$test1AuthHeader" "${baseUrl}randomuser/randomrepo:pull" 'All logged in users can pull all images.' + +# All logged in users can push all images that are in a namespace beginning with their name +testAuth "200" "$test1AuthHeader" "${baseUrl}test1/randomrepo:push" 'All logged in users can push all images that are in a namespace beginning with their name (1)' +testAuth "200" "$test1AuthHeader" "${baseUrl}test1-with-suffix/randomrepo:push" 'All logged in users can push all images that are in a namespace beginning with their name (2)' + +# Anonymous users can pull "hello-world". +testAuth "200" "" "${baseUrl}hello-world:pull" 'Anonymous users can pull "hello-world". (1)' +testAuth "200" "" "${baseUrl}randomuser/hello-world:pull" 'Anonymous users can pull "hello-world". (2)' + +# Access is denied by default. +testAuth "200" "$test1AuthHeader" "${baseUrl}randomuser/randomrepo:push" 'Access is denied by default.'