Giter VIP home page Giter VIP logo

ldap-acl-milter's Introduction

ldap-acl-milter

A lightweight, fast and thread-safe python3 milter on top of sdgathman/pymilter for basic Access Control (ACL) scenarios. The milter consumes policies from LDAP based on a specialized schema. Alternatively an already present schema can be uses as well. In this case custom queries with trivial templating support must be used:

  • %client_addr% = IPv(4|6) address of SMTP client
  • %sasl_user% = user name of SASL authenticated user
  • %from% = RFC5321.from
  • %from_domain% = RFC5321.from_domain
  • %rcpt% = RFC5321.rcpt
  • %rcpt_domain% RFC5321.rcpt_domain

In the case, one already has a LDAP server running with the amavis schema, for e.g. the 'amavisWhitelistSender' attribute could be reused. The filtering direction (inbound or outbound) can be simply controlled by swapping the %from% and %rcpt% placeholders within the LDAP query template. Please have a look at the docker-compose.yml example below.

The connection to the LDAP server is always persistent: one LDAP-bind is shared among all milter-threads, which makes it more efficient due to less communication overhead (which also implies transport encryption with TLS). Thus, LDAP interactions with 2 msec. and less are realistic, depending on your environment like network round-trip-times or the load of your LDAP server. A very swag LDAP setup is to use a local read-only LDAP replica, which syncs over network with a couple of LDAP masters: OpenLDAP does it for free!. On the one hand, this aproach eliminates network round trip times while reading from a UNIX-socket, and on the other, performance bottlenecks on a shared, centralized and (heavy) utilized LDAP server.

ldap-acl-milter´s own LDAP-schema

Yes, there´s one! Check out the LDAP-directory ;-)

Uniqueness of LDAP attributes

In case of OpenLDAP, just use the unique overlay. Another aproach to ensure attribute uniqueness is to do it in some programmatic way which is more complex but more flexible.

Deployment paradigm

The intention of this project is to deploy the milter ALWAYS AND ONLY as an OCI compliant container. In this case it´s docker. The main reason is that I´m not interested (and familiar with) in building distribution packages like .rpm, .deb, etc.. Furthermore I´m not really a fan of 'wild and uncontrollable' software deployments like: get the code, compile it and finaly install the results 'somewhere' in the filesystem. In terms of software deployment docker provides wonderful possibilities, which I don´t want to miss anymore... No matter if in development, QA or production stage.

docker-compose.yml

The following docker-compose file demonstrates how such a setup could be orchestrated on a single docker host or on a docker swarm cluster. In this context we use postfix as our milter-capable MTA and OpenLDAP as local LDAP replica.

version: '3'

volumes:
  lam_socket:
  openldap_spool:
  openldap_socket:

services:
  openldap:
    image: "your/favorite/openldap/image"
    restart: unless-stopped
    hostname: openldap
    volumes:
    - "./config/openldap:/etc/openldap:rw"
    - "openldap_spool:/var/openldap-data:rw"
    - "openldap_socket:/socket:rw"

  ldap-acl-milter:
    depends_on:
    - openldap
    image: "ldap-acl-milter/debian:19.02_master"
    restart: unless-stopped
    environment:
      # default: info. Possible: info, warning, error and debug
      LOG_LEVEL: debug
      #LDAP_SERVER: ldap://ldap-slave.example.local:389
      LDAP_SERVER: ldapi:///socket//slapd//slapd
      LDAP_BINDDN: uid=lam,ou=applications,dc=example,dc=org
      LDAP_BINDPW: TopSecret123!%&
      LDAP_BASE: ou=users,dc=example,dc=org
      # This example LDAP query is for inbound filtering
      # where the 'mail' attribute equals to the recipient
      # and the 'amavisWhitelistSender' attribute the eligible sender
      #LDAP_QUERY: (&(mail=%rcpt%)(amavisWhitelistSender=%from%))
      #LDAP_QUERY: (&(mail=%rcpt%)(|(amavisWhitelistSender=*@%from_domain%)(amavisWhitelistSender=%from%)))
      # LDAP_QUERY: (&(|(mail=%rcpt%)(mail=*@%rcpt_domain%))(|(amavisWhitelistSender=*@%from_domain%)(amavisWhitelistSender=%from%)))
      # This enables the use of own ldap-acl-milter LDAP schema. Default: False
      # Setting MILTER_SCHEMA: true disables the LDAP_QUERY parameter!
      #MILTER_SCHEMA: 'true'
      # If MILTER_SCHEMA_WILDCARD_DOMAIN is set to true, the milter allows *@domain
      # as valid sender/recipient addresses in LDAP.
      # This only works if MILTER_SCHEMA is enabled!
      MILTER_SCHEMA_WILDCARD_DOMAIN: 'False'
      # default: test. Possible: test, reject
      #MILTER_MODE: 'reject'
      MILTER_NAME: some-another-milter-name
      # Default: UNIX-socket located under /socket/ldap-acl-milter
      # https://pythonhosted.org/pymilter/namespacemilter.html#a266a6e09897499d8b1ae0e20f0d2be73
      #MILTER_SOCKET: inet6:8020
      #MILTER_REJECT_MESSAGE: Message rejected due to security policy
      #MILTER_TMPFAIL_MESSAGE: Message temporary rejected. Please try again later ;)
      # Expect authentication information from LDAP like allowedClientAddr,
      # allowedSaslUser or allowedx509CN. This is usefull if the milter handles
      # outbound email traffic, where senders must authenticate before submission.
      # Default: false (inbound mode)
      #MILTER_EXPECT_AUTH: 'true'
      # Blank or comma separated list of valid email recipients to whitelist (default: empty)
      #MILTER_WHITELISTED_RCPTS: '[email protected],[email protected]'
      # Allow null-sender (<>) for bounces/DSNs (default: disabled)
      #MILTER_ALLOW_NULL_SENDER: 'true'
      # Enable recipient count limits (default: disabled)
      #MILTER_MAX_RCPT_ENABLED: 'true'
      #MILTER_MAX_RCPT: 1
      # Enable DKIM checks (default: disabled).
      # This enables the milter to use the 
      # sender address placed in the 5322.from header
      # within policy checks, unless the DKIM authentication results
      # are invalid.
      # Enabling this feature also requires a DKIM validating milter
      # BEFORE the ldap-acl-milter!
      #MILTER_DKIM_ENABLED: 'true'
    hostname: ldap-acl-milter
    volumes:
    - "lam_socket:/socket/:rw"
    - "openldap_socket:/socket/slapd:ro"

  postfix:
    depends_on:
    - ldap-acl-milter
    image: "your/favorite/postfix/image"
    restart: unless-stopped
    hostname: postfix
    ports:
    - "25:25"
    volumes:
    - "./config/postfix:/etc/postfix:rw"
    - "lam_socket:/socket/ldap-acl-milter/:rw"
    - "openldap_socket:/socket/slapd:ro"

ldap-acl-milter's People

Contributors

chillout2k avatar

Stargazers

 avatar

Watchers

 avatar  avatar

ldap-acl-milter's Issues

LDAP schema defines an auxiliary class

Currently the schema defines a structural object with must attributes. If one wants to extend an already existing structural class this will fail as long as the mandatory attributes are not set as well.

Docker-build.sh should use ENV[http_proxy]

Currently the docker-build.sh script uses hard coded http proxy settings for the build process. It will be more sustainable to consume "traditional" environment variables instead.

SRS support

g_re_srs = re.compile(r"^SRS0=.+=.+=(\S+)=(\S+)\@.+$")
 

Ziele 107:

    # SRS (https://www.libsrs2.org/srs/srs.pdf)

    m_srs = g_re_srs.match(mailfrom)

    if m_srs != None:

      logging.info(self.mconn_id + "/FROM " +

        "Found SRS-encoded envelope-sender: " + mailfrom

      )

      mailfrom = m_srs.group(2) + '@' + m_srs.group(1)

      logging.info(self.mconn_id + "/FROM " +

        "SRS envelope-sender replaced with: " + mailfrom

      )

LDAP schema

A ldap-acl-milter specific schema would be nice!

Default Policy reject/permit

By default the milter rejects an email if no policy matches. In term of inbound email traffic the opposite will be neccessary: reject on demand.

Use preceded authentication (Sasl/x509)

Currently the milter checks only if there's a sender/recipient match, which is good for inbound scenarios. This feature takes the preceded authentication under attention, which provides more control over the authorization process in term of outbound scenarios.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.