-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Keycloak Authorization Services based authz prototype (#24)
* Keycloak Authz Services based authz prototype Signed-off-by: Marko Strukelj <[email protected]> * Address spotbugs issues Signed-off-by: Marko Strukelj <[email protected]> * Address PR comments Signed-off-by: Marko Strukelj <[email protected]> * Added initial authz test to testsuite Signed-off-by: Marko Strukelj <[email protected]> * Fix SpotBugs failure on Java 11 Signed-off-by: Marko Strukelj <[email protected]> * Add missing resource and action scope Signed-off-by: Marko Strukelj <[email protected]> * A more comprehensive test Signed-off-by: Marko Strukelj <[email protected]> * Fix JSONUtil.asListOfString() to convert non-textual values to text Signed-off-by: Marko Strukelj <[email protected]> * Fixes to examples/README-authz.md Signed-off-by: Marko Strukelj <[email protected]> * Rebase on master + improve README-authz.md + add DelegationToken resource for completeness Signed-off-by: Marko Strukelj <[email protected]> * Fix equals() method Signed-off-by: Marko Strukelj <[email protected]> * Fix UserSpec.of() method Signed-off-by: Marko Strukelj <[email protected]> * Throw exception for ACL methods if delegation to simple kafka ACL is not enabled Signed-off-by: Marko Strukelj <[email protected]> * Fix issues identified when testing with Kafka 2.4 and mutual TLS listeners Signed-off-by: Marko Strukelj <[email protected]> * Improve handling of non-oauth users and delegation to simple ACL Signed-off-by: Marko Strukelj <[email protected]> * Upgrade examples to Kafka 2.4.0 + oauthz example improvements Signed-off-by: Marko Strukelj <[email protected]> * Suggestions and comments from @tombentley Signed-off-by: Marko Strukelj <[email protected]> * Suggestions and comments from @tombentley Signed-off-by: Marko Strukelj <[email protected]> * Change strimzi.authz.* to strimzi.authorization.* Signed-off-by: Marko Strukelj <[email protected]> * Document authorization-scopes.json Signed-off-by: Marko Strukelj <[email protected]>
- Loading branch information
Showing
45 changed files
with
4,022 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
version: '3.5' | ||
|
||
services: | ||
|
||
#################################### KAFKA BROKER #################################### | ||
kafka: | ||
image: strimzi/example-kafka | ||
build: kafka-oauth-strimzi/kafka/target | ||
container_name: kafka | ||
ports: | ||
- 9092:9092 | ||
|
||
# javaagent debug port | ||
- 5006:5006 | ||
|
||
environment: | ||
|
||
# Java Debug | ||
KAFKA_DEBUG: y | ||
DEBUG_SUSPEND_FLAG: y | ||
JAVA_DEBUG_PORT: 5006 | ||
|
||
# | ||
# KAFKA Configuration | ||
# | ||
LOG_DIR: /home/kafka/logs | ||
|
||
KAFKA_BROKER_ID: 1 | ||
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 | ||
KAFKA_LISTENERS: REPLICATION://kafka:9091,CLIENT://kafka:9092 | ||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: REPLICATION:SSL,CLIENT:SASL_PLAINTEXT | ||
KAFKA_SASL_ENABLED_MECHANISMS: OAUTHBEARER | ||
KAFKA_INTER_BROKER_LISTENER_NAME: REPLICATION | ||
KAFKA_SSL_SECURE_RANDOM_IMPLEMENTATION: SHA1PRNG | ||
KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM: "" | ||
|
||
KAFKA_LISTENER_NAME_REPLICATION_SSL_KEYSTORE_LOCATION: /tmp/kafka/cluster.keystore.p12 | ||
KAFKA_LISTENER_NAME_REPLICATION_SSL_KEYSTORE_PASSWORD: Z_pkTh9xgZovK4t34cGB2o6afT4zZg0L | ||
KAFKA_LISTENER_NAME_REPLICATION_SSL_KEYSTORE_TYPE: PKCS12 | ||
KAFKA_LISTENER_NAME_REPLICATION_SSL_TRUSTSTORE_LOCATION: /tmp/kafka/cluster.truststore.p12 | ||
KAFKA_LISTENER_NAME_REPLICATION_SSL_TRUSTSTORE_PASSWORD: Z_pkTh9xgZovK4t34cGB2o6afT4zZg0L | ||
KAFKA_LISTENER_NAME_REPLICATION_SSL_TRUSTSTORE_TYPE: PKCS12 | ||
KAFKA_LISTENER_NAME_REPLICATION_SSL_CLIENT_AUTH: required | ||
|
||
KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_JAAS_CONFIG: "org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required;" | ||
KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_LOGIN_CALLBACK_HANDLER_CLASS: io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler | ||
KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_SERVER_CALLBACK_HANDLER_CLASS: io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler | ||
|
||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 | ||
|
||
KAFKA_AUTHORIZER_CLASS_NAME: io.strimzi.kafka.oauth.server.authorizer.KeycloakRBACAuthorizer | ||
KAFKA_PRINCIPAL_BUILDER_CLASS: io.strimzi.kafka.oauth.server.authorizer.JwtKafkaPrincipalBuilder | ||
|
||
KAFKA_STRIMZI_AUTHORIZATION_KAFKA_CLUSTER_NAME: cluster2 | ||
KAFKA_STRIMZI_AUTHORIZATION_DELEGATE_TO_KAFKA_ACL: "true" | ||
KAFKA_SUPER_USERS: User:CN=my-cluster-kafka,O=io.strimzi;User:CN=my-cluster-entity-operator,O=io.strimzi;User:CN=my-cluster-kafka-exporter,O=io.strimzi;User:service-account-kafka | ||
|
||
# | ||
# Strimzi OAuth Configuration | ||
# | ||
|
||
# Authentication config | ||
OAUTH_CLIENT_ID: "kafka" | ||
OAUTH_CLIENT_SECRET: "kafka-secret" | ||
OAUTH_TOKEN_ENDPOINT_URI: "http://${KEYCLOAK_HOST:-keycloak}:8080/auth/realms/${REALM:-kafka-authz}/protocol/openid-connect/token" | ||
|
||
# Validation config | ||
OAUTH_VALID_ISSUER_URI: "http://${KEYCLOAK_HOST:-keycloak}:8080/auth/realms/${REALM:-kafka-authz}" | ||
OAUTH_JWKS_ENDPOINT_URI: "http://${KEYCLOAK_HOST:-keycloak}:8080/auth/realms/${REALM:-kafka-authz}/protocol/openid-connect/certs" | ||
#OAUTH_INTROSPECTION_ENDPOINT_URI: "http://${KEYCLOAK_HOST}:8080/auth/realms/${REALM:-demo}/protocol/openid-connect/token/introspect" | ||
|
||
# username extraction from JWT token claim | ||
OAUTH_USERNAME_CLAIM: preferred_username | ||
|
||
# For start.sh script to know where the keycloak is listening | ||
KEYCLOAK_HOST: ${KEYCLOAK_HOST:-keycloak} | ||
REALM: ${REALM:-kafka-authz} | ||
|
||
zookeeper: | ||
image: strimzi/example-zookeeper | ||
build: kafka-oauth-strimzi/zookeeper/target | ||
container_name: zookeeper | ||
ports: | ||
- 2181:2181 | ||
environment: | ||
LOG_DIR: /home/kafka/logs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+5.13 KB
examples/docker/kafka-oauth-strimzi/kafka/certificates/cluster.keystore.p12
Binary file not shown.
Binary file added
BIN
+1.46 KB
examples/docker/kafka-oauth-strimzi/kafka/certificates/cluster.truststore.p12
Binary file not shown.
21 changes: 21 additions & 0 deletions
21
examples/docker/kafka-oauth-strimzi/kafka/certificates/gen-kafka-certs.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/bin/sh | ||
|
||
set -e | ||
|
||
STOREPASS=Z_pkTh9xgZovK4t34cGB2o6afT4zZg0L | ||
|
||
echo "#### Generate broker keystore" | ||
keytool -keystore cluster.keystore.p12 -alias localhost -validity 380 -genkey -keyalg RSA -ext SAN=DNS:kafka -dname "CN=my-cluster-kafka,O=io.strimzi" -deststoretype pkcs12 -storepass $STOREPASS -keypass $STOREPASS | ||
|
||
echo "#### Add the CA to the brokers’ truststore" | ||
keytool -keystore cluster.truststore.p12 -deststoretype pkcs12 -storepass $STOREPASS -alias CARoot -importcert -file ../../../certificates/ca.crt -noprompt | ||
|
||
echo "#### Export the certificate from the keystore" | ||
keytool -keystore cluster.keystore.p12 -storetype pkcs12 -alias localhost -certreq -file cert-file -storepass $STOREPASS | ||
|
||
echo "#### Sign the certificate with the CA" | ||
openssl x509 -req -CA ../../../certificates/ca.crt -CAkey ../../../certificates/ca.key -in cert-file -out cert-signed -days 400 -CAcreateserial -passin pass:$STOREPASS | ||
|
||
echo "#### Import the CA and the signed certificate into the broker keystore" | ||
keytool -keystore cluster.keystore.p12 -deststoretype pkcs12 -alias CARoot -import -file ../../../certificates/ca.crt -storepass $STOREPASS -noprompt | ||
keytool -keystore cluster.keystore.p12 -deststoretype pkcs12 -alias localhost -import -file cert-signed -storepass $STOREPASS -noprompt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/bin/bash | ||
|
||
if [ "$1" == "" ] || [ "$1" == "--help" ]; then | ||
echo "Usage: $0 [JSON_WEB_TOKEN]" | ||
exit 1 | ||
fi | ||
|
||
IFS='.' read -r -a PARTS <<< "$1" | ||
|
||
echo "Head: " | ||
echo $(echo -n "${PARTS[0]}" | base64 -d 2>/dev/null) | ||
echo | ||
echo "Payload: " | ||
echo $(echo -n "${PARTS[1]}" | base64 -d 2>/dev/null) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#!/bin/bash | ||
|
||
usage() { | ||
echo "Usage: $0 [USERNAME] [PASSWORD] [ARGUMENTS] ..." | ||
echo | ||
echo "$0 is a tool for obtaining an access token or a refresh token for the user or the client." | ||
echo | ||
echo " USERNAME The username for user authentication" | ||
echo " PASSWORD The password for user authentication (prompted for if not specified)" | ||
echo | ||
echo " If USERNAME and PASSWORD are not specified, client credentials as specified by --client-id and --secret will be used for authentication." | ||
echo | ||
echo " ARGUMENTS:" | ||
echo " --quiet, -q No informational outputs" | ||
echo " --insecure Allow http:// in token endpoint url" | ||
echo " --access Return access_token rather than refresh_token" | ||
echo " --endpoint TOKEN_ENDPOINT_URL Authorization server token endpoint" | ||
echo " --client-id CLIENT_ID Client id for client authentication - must be configured on authorization server" | ||
echo " --secret CLIENT_SECRET Secret to authenticate the client" | ||
echo " --scopes SCOPES Space separated list of scopes to request - default value: offline_access" | ||
} | ||
|
||
|
||
CLAIM=refresh_token | ||
GRANT_TYPE=password | ||
DEFAULT_SCOPES=offline_access | ||
|
||
while [ $# -gt 0 ] | ||
do | ||
case "$1" in | ||
"-q" | "--quiet") | ||
QUIET=1 | ||
;; | ||
--endpoint) | ||
shift | ||
TOKEN_ENDPOINT="$1" | ||
;; | ||
--insecure) | ||
INSECURE=1 | ||
;; | ||
--access) | ||
CLAIM=access_token | ||
DEFAULT_SCOPES="" | ||
;; | ||
--client-id) | ||
shift | ||
CLIENT_ID="$1" | ||
;; | ||
--secret) | ||
shift | ||
CLIENT_SECRET="$1" | ||
;; | ||
--scopes) | ||
shift | ||
SCOPES="$1" | ||
;; | ||
--help) | ||
usage | ||
exit 1 | ||
;; | ||
*) | ||
if [ "$UNAME" == "" ]; then | ||
UNAME="$1" | ||
elif [ "$PASS" == "" ]; then | ||
PASS="$1" | ||
else | ||
>&2 echo "Unexpected argument!" | ||
exit 1 | ||
fi | ||
;; | ||
esac | ||
shift | ||
done | ||
|
||
if [ "$TOKEN_ENDPOINT" == "" ]; then | ||
>&2 echo "ENV variable TOKEN_ENDPOINT not set." | ||
exit 1 | ||
fi | ||
|
||
if [ "$UNAME" != "" ] && [ "$PASS" == "" ]; then | ||
>&2 read -s -p "Password: " PASS | ||
>&2 echo | ||
fi | ||
|
||
if [ "$UNAME" == "" ] && [ "$CLIENT_ID" == "" ]; then | ||
echo "USERNAME not specified. Use --client-id and --secret to authenticate with client credentials." | ||
exit 1 | ||
fi | ||
|
||
if [ "$CLIENT_ID" == "" ]; then | ||
[ "$QUIET" == "" ] && >&2 echo "ENV var CLIENT_ID not set. Using default value: kafka-cli" | ||
CLIENT_ID=kafka-cli | ||
fi | ||
|
||
if [ "$UNAME" == "" ]; then | ||
GRANT_TYPE=client_credentials | ||
else | ||
USER_PASS_CLIENT="&username=${UNAME}&password=${PASS}&client_id=${CLIENT_ID}" | ||
fi | ||
|
||
if [ "$SCOPES" == "" ] && [ DEFAULT_SCOPES != "" ]; then | ||
[ "$QUIET" == "" ] && >&2 echo "ENV var SCOPES not set. Using default value: ${DEFAULT_SCOPES}" | ||
SCOPES="${DEFAULT_SCOPES}" | ||
fi | ||
|
||
if [ "$CLIENT_SECRET" != "" ]; then | ||
AUTH_VALUE=$(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64) | ||
AUTHORIZATION="-H 'Authorization: Basic ""$AUTH_VALUE'" | ||
fi | ||
|
||
[ "$QUIET" == "" ] && >&2 echo curl -s -X POST $TOKEN_ENDPOINT \ | ||
$AUTHORIZATION \ | ||
-H 'Content-Type: application/x-www-form-urlencoded' \ | ||
-d "grant_type=${GRANT_TYPE}${USER_PASS_CLIENT}&scope=${SCOPES}" | ||
|
||
result=$(curl -s -X POST $TOKEN_ENDPOINT \ | ||
$AUTHORIZATION \ | ||
-H 'Content-Type: application/x-www-form-urlencoded' \ | ||
-d "grant_type=${GRANT_TYPE}${USER_PASS_CLIENT}&scope=${SCOPES}") | ||
|
||
echo $result | awk -F "$CLAIM\":\"" '{printf $2}' | awk -F "\"" '{printf $1}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.