[rabbitmq-discuss] Creating an auth plugin (Kerberos)

Simon Lundström simlu at su.se
Tue Dec 11 19:38:03 GMT 2012

On Tue, 2012-12-11 at 17:07:02 +0000, Tim Watson wrote:
> That's not saying check_user_login is undefined. In fact, check_user_login is not even part of the NIF infrastructure. It looks like it's saying 'connection.start_ok' is undefined. Hmn - doesn't make much sense to me I'm afraid. What happens if you move the NIF part out into another module, using the -on_load attribute there and then just call that utility module from your plugin?
> -module(kinit).
> -export([init/0, kinit/2]).
> -on_load(init/0).
> init() ->
>   Kinit = code:priv_dir(?APPLICATION) ++ "/kinit.so",
>   erlang:load_nif(Kinit, 0).
> kinit(User, Password) -> exit(nif_library_not_loaded).

I just did this <https://github.com/simmel/rabbitmq-auth-backend-kerberos/commit/e645d21439> (browse here <https://github.com/simmel/rabbitmq-auth-backend-kerberos/tree/e645d21439d1c7d13216a53766918d69c6e7c04a>) and now I get:

=INFO REPORT==== 11-Dec-2012::20:09:32 ===  Management agent started.

=ERROR REPORT==== 11-Dec-2012::20:09:32 ===
WAT: {error,upgrade,"Upgrade not supported by this NIF library."}

=ERROR REPORT==== 11-Dec-2012::20:09:32 ===
WAT: ok

=INFO REPORT==== 11-Dec-2012::20:09:32 ===
Management plugin started. Port: 443, path: /

=INFO REPORT==== 11-Dec-2012::20:09:32 ===
Statistics database started.

=INFO REPORT==== 11-Dec-2012::20:09:46 ===
accepting AMQP connection <0.287.0> ( ->

=ERROR REPORT==== 11-Dec-2012::20:09:46 ===
WAT: {error,upgrade,"Upgrade not supported by this NIF library."}

=ERROR REPORT==== 11-Dec-2012::20:09:49 ===
closing AMQP connection <0.287.0> ( ->

when using AMQP login and this when I make an API call:

=CRASH REPORT==== 11-Dec-2012::20:10:27 ===  crasher:
    initial call: mochiweb_acceptor:init/3
    pid: <0.252.0>
    registered_name: []
    exception error: undefined function kinit:kinit/2
      in function  rabbit_auth_backend_kerberos:check_user_login/2
      in call from rabbit_access_control:'-check_user_login/2-fun-0-'/4
      in call from lists:foldl/3
      in call from rabbit_mgmt_app:'-make_loop/0-fun-0-'/4
      in call from mochiweb_http:headers/5
    ancestors: [rabbit_mochiweb_web_mgmt,rabbit_mochiweb_sup,<0.131.0>]
    messages: []    links: [<0.251.0>]
    dictionary: []
    trap_exit: false
    status: running
    heap_size: 4181
    stack_size: 24
    reductions: 1488

How bad are those upgrade errors?
AFAIK, I could just add an empty function in kinit.c and use them as
load, reload, upgrade and unload when doing ERL_NIF_INIT since I don't
really need to keep any "state"(?).

> Anyway, if you put the NIF part into another module, you *should* be able to test it outside of rabbit my doing something like:
> $ erl -sname foo
> banner. .....
> % ok = application:start(rabbit_auth_backend_kerberos).
> ok
> % X = kinit:kinit("auser", "password").
> << a term >>
> % io:format("~p~n", [X]).

I couldn't get that to work = / I'm probably doing it wrong, but here's what I did:

kaka:~/scm/rabbitmq-public-umbrella/rabbitmq-auth-backend-kerberos$ LDFLAGS="-L/usr/heimdal/lib -undefined dynamic_lookup -dynamiclib" CFLAGS="-I/usr/heimdal/include -I/usr/local/Cellar/erlang/R15B02/lib/erlang/usr/include/" make dist
[elided] generate deps
[elided] fix test deps
sed -e 's|build/deps.mk|$(DEPS_FILE)|' build/deps.mk > build/deps.mk.tmp && mv build/deps.mk.tmp build/deps.mk
ERL_LIBS=./build/dep-apps erlc -Wall +debug_info -I ./include -pa ebin -o ebin  src/kinit.erl
src/kinit.erl:14: Warning: variable 'Password' is unused
src/kinit.erl:14: Warning: variable 'User' is unused
escript ../generate_app src/rabbitmq_auth_backend_kerberos.app.src ebin/rabbitmq_auth_backend_kerberos.app ./src
sed -e 's|{vsn, *\"[^\"]*\"|{vsn,\"0.0.0\"|' <ebin/rabbitmq_auth_backend_kerberos.app >build/rabbitmq_auth_backend_kerberos.app.0.0.0
rm -rf build/app
mkdir -p ./build/app/rabbitmq_auth_backend_kerberos-0.0.0/ebin ./build/app/rabbitmq_auth_backend_kerberos-0.0.0/include
[elided] copy beams to ebin
cp -p ./build/rabbitmq_auth_backend_kerberos.app.0.0.0 ./build/app/rabbitmq_auth_backend_kerberos-0.0.0/ebin/rabbitmq_auth_backend_kerberos.app
mkdir -p ./build/app/rabbitmq_auth_backend_kerberos-0.0.0/priv
cp ./c_src/kinit.so ./build/app/rabbitmq_auth_backend_kerberos-0.0.0/priv
touch build/app/.done.0.0.0
rm -rf dist
mkdir -p dist
cd ./build/app/ && zip -q -r /Users/simlu/scm/rabbitmq-public-umbrella/rabbitmq-auth-backend-kerberos/dist/rabbitmq_auth_backend_kerberos-0.0.0.ez rabbitmq_auth_backend_kerberos-0.0.0
cp -r build/dep-ezs/amqp_client-0.0.0.ez build/dep-ezs/rabbit_common-0.0.0.ez ./dist
touch dist/.done.0.0.0
touch dist/.done
$ cd ebin
$ erl -sname `hostname -s`
Erlang R15B02 (erts-5.9.2) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false] [dtrace]

Eshell V5.9.2  (abort with ^G)
(kaka at kaka)1> ok = application:start(rabbitmq_auth_backend_kerberos).
** exception error: no match of right hand side value {error,{not_started,inets}}
(kaka at kaka)2> kinit:kinit("auser", "password").
WAT: ok

This doesn't really test the whole thing since rabbitmq isn't really
involved or even loaded. Kind of feels like cheating = )

I have had this NIF-code to work outside of RabbitMQ, that's how I wrote
it originally.

(also, do get it working I changed the hardencoded path to match the
path on my Mac and I changed "rabbit_log:error" to "io:fwrite" since
RabbitMQ wasn't loaded correctly in my erl.

> Then if it *still* doesn't work when you're running it inside rabbit we might need to consider other things that could be going wrong (such as the NIF init magic). 

I have no idea, but this seems more and more likely.

- Simon

More information about the rabbitmq-discuss mailing list