processone / ejabberd-contrib

Growing and curated ejabberd contributions repository - PR or ask to join !
http://ejabberd.im
248 stars 137 forks source link

ejabberd_auth_http compilation fails with ejabberd/ecs:23.04 #318

Open andrewkoltsov opened 1 year ago

andrewkoltsov commented 1 year ago

I'm trying to build docker image based on ejabberd/ecs:23.04 with ejabberd_auth_http installed, there is my docker image

FROM ejabberd/ecs:23.04

USER root
RUN set -xe \
    && apk add --update --no-cache --virtual .build-deps \
        build-base \
        erlang-dev \
        git \
        mc

USER ejabberd

# Clone the ejabberd-contrib repository
RUN git clone https://github.com/processone/ejabberd-contrib.git ~/ejabberd-contrib
RUN cd ~/ejabberd-contrib/ejabberd_auth_http && \
    mkdir ebin && \
    erlc \
    -o ebin \
    -I include -I /home/ejabberd/lib/ejabberd-23.4.0/include \
    -DLAGER -DNO_EXT_LIB \
    src/*erl

But, unfortunately, docker build . fails on erlc comand with src/ejabberd_auth_http.erl: undefined parse transform 'lager_transform', I took a look at ejabberd_auth_http code, there is no usage of lager

What is the correct way to build docker image with ejabberd_auth_http module?

licaon-kter commented 1 year ago

You want to modify it?

andrewkoltsov commented 1 year ago

with

~/bin/erlc \
    -o ebin \
    -I include -I /home/ejabberd/lib/ejabberd-23.4.0/include \
    -DLAGER -DNO_EXT_LIB \
    src/*erl

it fails too with init terminating in do_boot ({cannot get bootfile,no_dot_erlang.boot})

andrewkoltsov commented 1 year ago

@licaon-kter actually I did a minor modification: add trailing slash to make it work with my rest api

andrewkoltsov commented 1 year ago

I made it compile with

FROM ejabberd/ecs:23.04

USER root
RUN set -xe \
    && apk add --update --no-cache --virtual .build-deps \
        build-base \
        erlang-dev \
        git \
        mc

USER ejabberd

# Clone the ejabberd-contrib repository
RUN git clone https://github.com/processone/ejabberd-contrib.git ~/ejabberd-contrib
ENV ERL_LIBS=/home/ejabberd/lib
RUN cd ~/ejabberd-contrib/ejabberd_auth_http && \
    mkdir ebin && \
    erlc \
    -o ebin \
    -I include -I /home/ejabberd/lib/ejabberd-23.4.0/include -I /home/ejabberd/lib/xmpp-1.6.2/include \
    -DNO_EXT_LIB \
    src/*erl
badlop commented 1 year ago

The ejabberd alternate image already includes the ejabberd-contrib sources, with that one you would just need to install the desired modules (and of course later configure them in the configuration file):

$ docker run --name ejabberd -d -p 5222:5222 ghcr.io/processone/ejabberd
61836193d4250a8b45150aa522c91bf93829197ab52bfe926d0542d83e9f7843

$ docker exec -it ejabberd ejabberdctl module_install ejabberd_auth_http
Module ejabberd_auth_http has been installed.
Now you can configure it in your ejabberd.yml

You could automatize this using the CTL_ON_CREATE environment variable that is read by ejabberdctl. For example in docker-compose.yml

version: '3.7'
services:
  main:
    image: ghcr.io/processone/ejabberd
    container_name: ejabberd
    environment:
      - CTL_ON_CREATE=module_install ejabberd_auth_http
    ports:
      - "5222:5222"

When it starts for the first time, it will instal that module:

...
ejabberd | 2023-05-17 14:36:43.748863+00:00 [info] ejabberd 23.1.0 is started in the node ejabberd@localhost in 3.88s
...
ejabberd | :> ejabberdctl module_install ejabberd_auth_http
ejabberd | Module ejabberd_auth_http has been installed.
ejabberd | Now you can configure it in your ejabberd.yml

When using the ecs image, as the sources are not included, you can use CTL_ON_CREATE to first get the sources, and then install the module:

    environment:
      - CTL_ON_CREATE=modules_update_specs ;
                      module_install ejabberd_auth_http
andrewkoltsov commented 1 year ago

thank you, actually I'm running ejabberd in k8s, and I'm not sure that CTL_ON_CREATE approach will work, because I'm expecting to have an image with everything installed and ready ejabberd.yml

andrewkoltsov commented 1 year ago

but now i have strange issue, when I'm trying to authenticate with port forwarding via lens app, that's why you may see 127.0.0.1, may be port forwarding is a root cause of an issue

2023-05-17 15:21:56.926296+00:00 [info] (<0.1242.0>) Accepted connection 127.0.0.1:40306 -> 127.0.0.1:5222
2023-05-17 15:21:56.930478+00:00 [info] (<0.1243.0>) Accepted connection 10.244.2.58:37582 -> 10.244.2.1:5222
2023-05-17 15:21:57.098367+00:00 [error] ** Generic server <0.1242.0> terminating 
** Last message in was {'$gen_event',
                           {xmlstreamelement,
                               {xmlel,<<"auth">>,
                                   [{<<"xmlns">>,
                                     <<"urn:ietf:params:xml:ns:xmpp-sasl">>},
                                    {<<"mechanism">>,<<"PLAIN">>}],
                                   [{xmlcdata,<<"AGFuZHJleQAxMjM=">>}]}}}
** When Server state == #{stream_authenticated => false,
                          stream_encrypted => false,tls_verify => false,
                          mgmt_resend => if_offline,
                          server => <<"my_own_domain.me">>,
                          stream_compressed => false,zlib => false,
                          owner => <0.1242.0>,mgmt_stanzas_req => 0,
                          resource => <<>>,lserver => <<"my_own_domain.me">>,
                          pres_a => {0,nil},
                          stream_direction => in,user => <<>>,
                          mgmt_max_queue => 5000,mgmt_max_timeout => 300000,
                          mgmt_ack_timeout => 60000,
                          csi_queue => {0,#{}},
                          lang => <<"en">>,mgmt_stanzas_out => 0,
                          mgmt_stanzas_in => 0,
                          stream_id => <<"3526918123645842619">>,
                          ip => {{127,0,0,1},40306},
                          socket_monitor =>
                              #Ref<0.2565508618.376176642.232860>,
                          mod => ejabberd_c2s,stream_restarted => false,
                          mgmt_queue_type => ram,mgmt_timeout => 300000,
                          shaper => c2s_shaper,tls_required => false,
                          access => c2s,
                          stream_version => {1,0},
                          stream_header_sent => true,
                          stream_state => wait_for_sasl_request,
                          tls_enabled => false,
                          stream_timeout => {30000,-576460253507},
                          codec_options => [ignore_els],
                          xmlns => <<"jabber:client">>,
                          tls_options => [compression_none],
                          mgmt_state => inactive,csi_state => active,
                          socket =>
                              {socket_state,gen_tcp,#Port<0.101>,262144,
                                  #Ref<0.2565508618.376307714.232859>,
                                  {state,1000000,1000000,1000000,
                                      1684336917044104},
                                  none}}
** Reason for termination == 
** {'module could not be loaded',
       [{cuesport,get_worker,['ejabberd_auth_http_my_own_domain.me'],[]},
        {ejabberd_auth_http,make_req,5,
            [{file,"src/ejabberd_auth_http.erl"},{line,213}]},
        {ejabberd_auth_http,check_password,4,
            [{file,"src/ejabberd_auth_http.erl"},{line,64}]},
        {ejabberd_auth,db_check_password,7,
            [{file,"src/ejabberd_auth.erl"},{line,693}]},
        {ejabberd_auth,'-check_password_with_authmodule/6-fun-0-',8,
            [{file,"src/ejabberd_auth.erl"},{line,250}]},
        {lists,foldl,3,[{file,"lists.erl"},{line,1267}]},
        {ejabberd_auth,check_password_with_authmodule,6,
            [{file,"src/ejabberd_auth.erl"},{line,248}]},
        {xmpp_sasl_plain,mech_step,2,
            [{file,"/ejabberd/deps/xmpp/src/xmpp_sasl_plain.erl"},
             {line,42}]}]}

            [{file,"src/ejabberd_auth.erl"},{line,248}]},
        {xmpp_sasl_plain,mech_step,2,
            [{file,"/ejabberd/deps/xmpp/src/xmpp_sasl_plain.erl"},
             {line,42}]}]}

2023-05-17 15:21:57.100264+00:00 [error] CRASH REPORT:
  crasher:
    initial call: xmpp_stream_in:init/1
    pid: <0.1242.0>
    registered_name: []
    exception exit: {undef,
                        [{cuesport,get_worker,
                             ['ejabberd_auth_http_my_own_domain.me'],
                             []},
                         {ejabberd_auth_http,make_req,5,
                             [{file,"src/ejabberd_auth_http.erl"},{line,213}]},
                         {ejabberd_auth_http,check_password,4,
                             [{file,"src/ejabberd_auth_http.erl"},{line,64}]},
                         {ejabberd_auth,db_check_password,7,
                             [{file,"src/ejabberd_auth.erl"},{line,693}]},
                         {ejabberd_auth,
                             '-check_password_with_authmodule/6-fun-0-',8,
                             [{file,"src/ejabberd_auth.erl"},{line,250}]},
                         {lists,foldl,3,[{file,"lists.erl"},{line,1267}]},
                         {ejabberd_auth,check_password_with_authmodule,6,
                             [{file,"src/ejabberd_auth.erl"},{line,248}]},
                         {xmpp_sasl_plain,mech_step,2,
                             [{file,
                                  "/ejabberd/deps/xmpp/src/xmpp_sasl_plain.erl"},
                              {line,42}]}]}
      in function  p1_server:terminate/7 (/ejabberd/deps/p1_utils/src/p1_server.erl, line 878)
    ancestors: [ejabberd_c2s_sup,ejabberd_sup,<0.887.0>]
    message_queue_len: 0
    messages: []
    links: [<0.1182.0>]
    dictionary: [{already_terminated,true},
                  {rand_seed,{#{bits => 58,jump => #Fun<rand.3.92093067>,
                                next => #Fun<rand.0.92093067>,type => exsss,
                                uniform => #Fun<rand.1.92093067>,
                                uniform_n => #Fun<rand.2.92093067>},
                              [105396063504397610|172215626675652448]}},
                  {'$internal_queue_len',0}]
    trap_exit: false
    status: running
    heap_size: 10958
    stack_size: 28
    reductions: 63233
  neighbours:

  2023-05-17 15:21:57.110793+00:00 [error] SUPERVISOR REPORT:
    supervisor: {local,ejabberd_c2s_sup}
    errorContext: child_terminated
    reason: {undef,
                [{cuesport,get_worker,['ejabberd_auth_http_my_own_domain.me'],[]},
                 {ejabberd_auth_http,make_req,5,
                     [{file,"src/ejabberd_auth_http.erl"},{line,213}]},
                 {ejabberd_auth_http,check_password,4,
                     [{file,"src/ejabberd_auth_http.erl"},{line,64}]},
                 {ejabberd_auth,db_check_password,7,
                     [{file,"src/ejabberd_auth.erl"},{line,693}]},
                 {ejabberd_auth,'-check_password_with_authmodule/6-fun-0-',8,
                     [{file,"src/ejabberd_auth.erl"},{line,250}]},
                 {lists,foldl,3,[{file,"lists.erl"},{line,1267}]},
                 {ejabberd_auth,check_password_with_authmodule,6,
                     [{file,"src/ejabberd_auth.erl"},{line,248}]},
                 {xmpp_sasl_plain,mech_step,2,
                     [{file,"/ejabberd/deps/xmpp/src/xmpp_sasl_plain.erl"},
                      {line,42}]}]}
    offender: [{pid,<0.1242.0>},
               {id,undefined},
               {mfargs,{ejabberd_c2s,start_link,undefined}},
               {restart_type,temporary},
               {significant,false},
               {shutdown,5000},
               {child_type,worker}]
2023-05-17T15:21:57.112964542Z
badlop commented 1 year ago

I'm not sure that CTL_ON_CREATE approach will work, because I'm expecting to have an image with everything installed and ready ejabberd.yml

Ah right. ejabberd needs to be running to use module_install. But if you define the module in ejabberd.yml before installing the module, then ejabberd refuses to start... deadlock.

I'm playing now with a new option that would allow to bypass this strict configuration checking somehow. That would allow you to configure as you wish in ejabberd.yml, and ejabberd will take care to install the modules as required.

** Reason for termination == 
** {'module could not be loaded',
       [{cuesport,get_worker,['ejabberd_auth_http_my_own_domain.me'],[]},
        {ejabberd_auth_http,make_req,5,
            [{file,"src/ejabberd_auth_http.erl"},{line,213}]},

    reason: {undef,
                [{cuesport,get_worker,['ejabberd_auth_http_my_own_domain.me'],[]},
                 {ejabberd_auth_http,make_req,5,
                     [{file,"src/ejabberd_auth_http.erl"},{line,213}]},

ejabberd_auth_http requires the cuesport and fusco libraries, as defined in its rebar.config. When installing with module_install, that file is read and its libraries downloaded, compiled and installed. If you use an alternate compilation method, do you take care of those dependencies?

Neustradamus commented 1 year ago

@andrewkoltsov: Have you looked the @badlop comment?

badlop commented 1 year ago

I'm expecting to have an image with everything installed and ready ejabberd.yml

Good news. Since this commit you can use the new option install_contrib_modules

Configure in ejabberd.yml whatever modules from ejabberd-contrib, and mention them in the new option, so ejabberd installs them when it's starting. For example:

allow_contrib_modules: true

install_contrib_modules:
  - ejabberd_auth_http
  - mod_default_rooms
  - mod_statsdx
  - mod_shcommands
  - mod_webadmin_config
  - mod_webpresence

auth_method: http
auth_opts:
  host: "http://localhost:12000"

listen:
  ...
  -
    port: 5284
    module: ejabberd_http
    request_handlers:
      /presence3: mod_webpresence

modules:
  ...
  mod_default_rooms:
    rooms:
      - foo@conference.example.net
      - bar@conference.example.org
  mod_statsdx:
    hooks: true

That way you don't need to compile or install them.

Simply make sure to have the source code downloaded. You download the source code in the Dockerfile:

RUN git clone https://github.com/processone/ejabberd-contrib.git ~/ejabberd-contrib

But I think that you should download to ~/.ejabberd-modules/sources/. That's the destination path when downloading from git as seen in ejabberd-contrib's ci.yml