SSSD / sssd

A daemon to manage identity, authentication and authorization for centrally-managed systems.
https://sssd.io
GNU General Public License v3.0
588 stars 237 forks source link

sssd container support #5443

Open holmanb opened 3 years ago

holmanb commented 3 years ago

Outside of the "Redhat Atomic" world, it appears that authenticating a containerized service via sssd requires running sssd on the host and bind mounting /var/lib/sss/pipes/ into the container. While this works, it limits containerized auth to a single set of domains, which doesn't allow multi-tenancy.

It appears that some thought went into this problem, however that proposal currently sits in the "not implemented list" and a quick grep of the codebase and open issues leaves no indication that this issue has been worked on, or is being looked at. Is there some other approach to solving this problem that I haven't found documentation for perhaps?

I assume that the benefits of supporting the broader containerization ecosystem would be twofold - wider adoption and greater community contribution. As it stands, it doesn't appear that sssd fits my needs, though I would love to see this as a feature in sssd.

alexey-tikhonov commented 5 months ago

Hi, @holmanb

(I know it's been a long since you reported this, but just in case if you would be available to answer)

what was your use case, why SSSD didn't fit and what was the issue with running SSSD in the container?

While no 'ready to use' image was provided (mostly due to lack of demand / understanding of use cases), some folks were building such containers for their needs (see for example: https://blog.rook.io/prototyping-an-nfs-connection-to-ldap-using-sssd-7c27f624f1a4)

alexey-tikhonov commented 5 months ago

One of potential issues could be that SSSD was typically run under the root / required a set of certain privileges, thus putting limitation on a container runtime engine (user-ns support).

The ability to run under non-root user / without privileges is going to be greatly improved with upcoming sssd-2.10 release.

JFTR, following patches are relevant:

davidmather commented 5 months ago

Hi @alexey-tikhonov

I suppose the use case would be 6G. We want to use kubernetes to basically have a situation where there is a load on the network for example a football game or concert we can scale up the number of replicas to meet demand as networks are generally bottlenecked by backend compute rather than the cell phone towers themselves. The cell phone towers use sssd/sshd/vsftpd to synchronize state, handle cell phone calls etc. Unfortunately countries have gotten more strict in what they allow to be running on a network and have pretty much mandated that non-root is mandatory.

KR Dave

alexey-tikhonov commented 5 months ago

Hi @davidmather,

thank you.

We want to use kubernetes

Could you please provide very high level arch overview (if possible)? Do you run SSSD + custom app in a single container?

non-root is mandatory

'non-root' - where / what does it actually mean? For example: does 'rootless' docker/podman, where container engine runs under non-root, but application within container namespace might run under uid=0 / with unrestricted capabilities, satisfy this requirement?

davidmather commented 5 months ago

Hi @alexey-tikhonov

For example: does 'rootless' docker/podman, where container engine runs under non-root, but application within container namespace might run under uid=0 / with unrestricted capabilities, satisfy this requirement?

No we have this already they are looking for Openshift restricted-v2.

SSSD doesn't require unrestricted capabilites even with the old version (we have a capabilities testing tool). Just chmod u+s sssd sshd vsftpd. We have a timeline for early 2025 for everything to be fixed so we have kind of left this on the long finger as we have 100+ other containers to implement that don't require sssd but now we have approx 30 left so pressure back on to fix this.

    securityContext:
      allowPrivilegeEscalation: true
      capabilities:
        add:
        - DAC_OVERRIDE
        - SETGID
        - AUDIT_WRITE
        - SETUID
        - CHOWN
        - SETPCAP
        - FOWNER
        - FSETID
        - KILL
        - MKNOD
        - NET_RAW
        - NET_BIND_SERVICE
        - SYS_CHROOT
        drop:
        - all
      privileged: false
      readOnlyRootFilesystem: true
      runAsNonRoot: true

eccd@director-0-ccd-c16c002:~> kubectl exec -it filetransferservice-5f8d497659-j7bkd -- bash Defaulted container "filetransferservice" out of: filetransferservice, filetransferservice-monitoring, filetransferservice-wait (init), filetransferservice-waitforcerts (init) filetransferservice-5f8d497659-j7bkd:/ # ls -l /home/smrs total 24 drwxr-xr-x 5 root root 4096 Mar 20 17:50 3ppsoftware drwxr-xr-x 2 root root 4096 Mar 20 17:50 dev drwxr-xr-x 5 root root 4096 Mar 20 17:48 MINI-LINK drwxr-xr-x 2 root root 4096 Mar 20 18:32 oradio drwxrwsr-x 19 jboss_user mm-smrsusers 4096 Mar 22 14:05 smrsroot drwxr-xr-x 2 root root 4096 Mar 20 18:32 software filetransferservice-5f8d497659-j7bkd:/ # ls -l /home/smrs/MINI-link ls: cannot access '/home/smrs/MINI-link': No such file or directory filetransferservice-5f8d497659-j7bkd:/ # ls -l /home/smrs/smrsroot total 68 drwxrwsr-x 5 jboss_user mm-smrsusers 4096 Mar 20 21:04 ai drwxrwsr-x 141 jboss_user mm-smrsusers 4096 Mar 21 03:00 backup drwxrwsr-x 3 jboss_user mm-smrsusers 4096 Mar 20 21:04 certificates drwxrwsr-x 4 jboss_user mm-smrsusers 4096 Mar 20 21:01 cm_models drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 21 12:32 flightrecording drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 20 22:18 jobreporting drwxrwsr-x 6 jboss_user mm-smrsusers 4096 Mar 20 21:03 licence drwxrwsr-x 4 jboss_user mm-smrsusers 4096 Mar 20 20:40 nl drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 20 18:32 nodecli drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 20 17:47 pm_push_1 drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 20 17:47 pm_push_2 drwxrwsr-x 5 jboss_user mm-smrsusers 4096 Mar 22 00:00 sftppslog drwxrwsr-x 3 jboss_user mm-smrsusers 4096 Mar 20 19:58 shm_view_inventory drwxrwsr-x 128 jboss_user mm-smrsusers 4096 Mar 20 19:47 software drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 20 17:51 stolen_scraped_equipment drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 21 12:32 ul_spectrum_files drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 20 17:49 upgrade_independence filetransferservice-5f8d497659-j7bkd:/ # ls -l /pmic1 total 64 drwxr-xr-x 4 root root 4096 Mar 20 20:38 asn1 drwxr-xr-x 2 root root 4096 Mar 21 04:00 CELLTRACE drwxr-xr-x 2 root root 4096 Mar 20 22:06 coreTopology drwxr-xr-x 2 root root 4096 Mar 21 04:00 CTR drwxrwsr-x 3 106886 enm 4096 Mar 22 10:50 ebsl drwxrwsr-x 4 106886 enm 4096 Mar 22 10:50 ebsm drwxrwsr-x 3 106886 enm 4096 Mar 22 10:50 ebsn drwxrwxr-x 2 jboss_user jboss 4096 Mar 20 17:27 fls drwxrwsr-x 2 jboss_user jboss 4096 Mar 20 22:14 fls_file_already_exist drwxr-xr-x 2 root root 4096 Mar 21 04:00 GPEH drwxr-xr-x 2 root root 4096 Mar 20 22:06 lteTopology drwxrwsr-x 2 jboss_user mm-smrsusers 4096 Mar 20 17:47 tmp_push drwxr-xr-x 4 root root 4096 Mar 20 17:50 tmp_push_ml drwxr-xr-x 2 root root 4096 Mar 21 04:00 UETR drwxr-xr-x 4 root root 4096 Mar 20 19:51 wcdmaTopology drwxr-xr-x 16 root root 4096 Mar 20 22:50 XML filetransferservice-5f8d497659-j7bkd:/ # ls -l /ericsson/pmic1/XML total 100 drwxr-xr-x 2 root root 4096 Mar 21 04:00 1MIN drwxr-xr-x 2 root root 4096 Mar 20 22:05 'MeContext=CORE126EPG002,ManagedElement=CORE126EPG002' drwxr-xr-x 2 root root 4096 Mar 20 22:05 'MeContext=CORE126EPG003,ManagedElement=CORE126EPG003' drwxr-xr-x 2 root root 4096 Mar 20 22:11 'MeContext=CORE31BSP003,ManagedElement=CORE31BSP003' drwxr-xr-x 2 root root 4096 Mar 20 22:14 'MeContext=CORE31BSP004,ManagedElement=CORE31BSP004' drwxr-xr-x 2 root root 4096 Mar 20 22:50 'MeContext=CORE67FrontHaul608001,ManagedElement=1' drwxr-xr-x 2 root root 4096 Mar 20 22:31 'MeContext=LTE125ERBS00011' drwxr-xr-x 2 root root 4096 Mar 20 22:33 'MeContext=LTE125ERBS00013' drwxr-xr-x 2 root root 4096 Mar 20 20:32 'MeContext=LTE125ERBS00014' drwxr-xr-x 2 root root 12288 Mar 20 22:30 'NetworkElement=CORE107EIRFE0002' drwxr-xr-x 2 root root 12288 Mar 20 22:31 'NetworkElement=CORE107EIRFE0004' drwxr-xr-x 2 root root 12288 Mar 22 14:05 'SubNetwork=RNC05,MeContext=RNC05' drwxr-xr-x 2 root root 16384 Mar 22 13:35 'SubNetwork=RNC08,MeContext=RNC08' drwxr-xr-x 2 root root 12288 Mar 22 14:05 'SubNetwork=RNC10,MeContext=RNC10' filetransferservice-5f8d497659-j7bkd:/ # ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 Mar21 ? 00:00:41 /sbin/init root 28 1 0 Mar21 ? 00:00:09 /usr/lib/systemd/systemd-journald message+ 30 1 0 Mar21 ? 00:00:32 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd root 171 1 0 Mar21 ? 00:00:00 /usr/sbin/sssd -i --logger=files root 176 171 0 Mar21 ? 00:00:01 /usr/lib/sssd/sssd_be --domain enm_ldap_local --uid 0 --gid 0 --logger=files root 177 171 0 Mar21 ? 00:01:32 /usr/lib/sssd/sssd_be --domain enm_ldap_remote --uid 0 --gid 0 --logger=files root 178 171 0 Mar21 ? 00:00:02 /usr/lib/sssd/sssd_nss --uid 0 --gid 0 --logger=files root 179 171 0 Mar21 ? 00:00:00 /usr/lib/sssd/sssd_pam --uid 0 --gid 0 --logger=files root 180 171 0 Mar21 ? 00:00:02 /usr/lib/sssd/sssd_ifp --uid 0 --gid 0 --logger=files root 181 1 0 Mar21 ? 00:00:01 /usr/sbin/cron -n root 182 1 0 Mar21 ? 00:00:16 /usr/lib/systemd/systemd-logind root 356 1 0 Mar21 ? 00:00:00 /usr/sbin/rsyslogd -n -iNONE root 767 1 0 Mar21 ? 00:00:00 /usr/sbin/vsftpd /etc/vsftpd/ftpes_ipv6.conf -obackground=YES root 832 1 0 Mar21 ? 00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 1000-1000 startups root 693888 0 0 14:04 pts/0 00:00:00 bash root 695453 693888 0 14:06 pts/0 00:00:00 ps -ef filetransferservice-5f8d497659-j7bkd:/ #

alexey-tikhonov commented 5 months ago

No we have this already they are looking for Openshift restricted-v2.

It's not exactly what I meant. Since currently Openshift doesn't support user-namespaces, you have to grant capabilities (in 'securityContext') in the host namespace.

Well, I think it's a matter of time when Openshift gets https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/127-user-namespaces/README.md , so you should be able to restrict (revoke all capabilities) your pod in the host namespace but keep running your container (more or less) using just 'hostUsers = false'

root 1 0 0 Mar21 ? 00:00:41 /sbin/init root 28 1 0 Mar21 ? 00:00:09 /usr/lib/systemd/systemd-journald message+ 30 1 0 Mar21 ? 00:00:32 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd root 171 1 0 Mar21 ? 00:00:00 /usr/sbin/sssd -i --logger=files root 176 171 0 Mar21 ? 00:00:01 /usr/lib/sssd/sssd_be --domain enm_ldap_local --uid 0 --gid 0 --logger=files ... root 181 1 0 Mar21 ? 00:00:01 /usr/sbin/cron -n root 182 1 0 Mar21 ? 00:00:16 /usr/lib/systemd/systemd-logind root 356 1 0 Mar21 ? 00:00:00 /usr/sbin/rsyslogd -n -iNONE root 767 1 0 Mar21 ? 00:00:00 /usr/sbin/vsftpd /etc/vsftpd/ftpes_ipv6.conf -obackground=YES root 832 1 0 Mar21 ? 00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 1000-1000 startups

So you have everything packed into a single systemd based container... If you want to run this container in Openshift without user-ns support, then non-privileged SSSD is only one of required bits. Among other things (or first of all), you would have to get rid of 'systemd' usage...

What 'auth_provider' is used in your sssd.conf?

davidmather commented 5 months ago

So you have everything packed into a single systemd based container... If you want to run this container in Openshift without user-ns support, then non-privileged SSSD is only one of required bits.

Yes this is true the plan is to either replace systemd with catatonit https://github.com/openSUSE/catatonit or remove it entirely and cron with https://github.com/aptible/supercronic

vsftpd + sshd have coding issues that I am looking into at the moment. (mostly to do with the use of chroot which could be swapped for kubernetes subpaths.)

What 'auth_provider' is used in your sssd.conf?

filetransferservice-5f8d497659-j7bkd:/ # cat /etc/sssd/sssd.conf [sssd] domains = enm_ldap_local,enm_ldap_remote domain_resolution_order=enm_ldap_local,enm_ldap_remote full_name_format=%1$s config_file_version = 2 services = nss, pam, ifp debug_level = 1

[pam] debug_level = 1 cache_first = True

[nss] debug_level = 1 cache_first = Trueldap_tls_cacert = /tmp/opendj_cert.pem filetransferservice-5f8d497659-j7bkd:/ # cat /etc/sssd/conf.d/ldap_local.conf [domain/enm_ldap_local] id_provider = ldap auth_provider = ldap access_provider = permit ldap_schema = rfc2307bis ldap_group_member = uniqueMember ldap_search_base = dc=ieatenmc16c002,dc=com

ldap_user_search_base

ldap_group_search_base

ldap_uri = ldaps://ldap-local:1636 ldap_default_bind_dn = cn=directory manager ldap_default_authtok = Idapadmin enumerate = False default_shell = /bin/bash debug_level = 1 ldap_tls_reqcert = never ldap_id_use_start_tls = false

Allow for offline logins by locally storing password hashes (default: false).

cache_credentials = truefiletransferservice-5f8d497659-j7bkd:/ # cat /etc/sssd/conf.d/ldap_remote.conf [domain/enm_ldap_remote] id_provider = ldap auth_provider = ldap access_provider = permit ldap_schema = rfc2307bis ldap_group_member = uniqueMember ldap_search_base = dc=ieatenmc16c002,dc=com

ldap_user_search_base

ldap_group_search_base

ldap_uri = ldaps://ldap-remote:1636 ldap_default_bind_dn = cn=directory manager ldap_default_authtok = Idapadmin enumerate = False default_shell = /bin/bash debug_level = 1 ldap_tls_reqcert = never ldap_id_use_start_tls = false

Allow for offline logins by locally storing password hashes (default: false).

cache_credentials = true

alexey-tikhonov commented 5 months ago

SSSD doesn't require unrestricted capabilites even with the old version (we have a capabilities testing tool).

It did (and some bits still do). Depending on build config, sssd-2.9- versions might use CAP_CHOWN, CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_SETGID, CAP_SETUID, ... in specific code paths.

Just chmod u+s sssd sshd vsftpd.

This already requires CAP_SETUID for pod.

As I understand it, you have two options:

auth_provider = ldap

This makes things easier. You don't need Kerberos, so don't need 'krb5_child'/'ldap_child' (and 'selinux_child') -- those are the only helpers that still want some capabilities in sssd-2.10: https://github.com/SSSD/sssd/blob/0d5e8f11714e8e6cc0ad28e03fecf0f5732528b3/contrib/sssd.spec.in#L20

What base image do you use?

davidmather commented 5 months ago

Just chmod u+s sssd sshd vsftpd.

This already requires CAP_SETUID for pod.

No u+s doesn't use CAP_SETUID just allowPrivilegeEscalation: true.

However to avoid SETUID we are modifying the Kubernetes ingress to route packets based on the UID required. So you would have a container for each user with the correct subpaths specified for that user then avoid calling setuid entirely.

re-design your container so it doesn't require any privileges/capabilities (in any namespace)

We can run vsftpd/sshd without any capabilities/privileges assuming the above statement is true and setuid is avoided.

CAP_CHOWN, CAP_DAC_READ_SEARCH, CAP_FOWNER

These are generally required due to incorrect filesystem permissions. Are they still required with chmod -R 777 / ?? possibly the files being accessed would need to change

What base image do you use?

We have a local RHEL mirror and generally build from scratch and pull in the RPMs we need.

alexey-tikhonov commented 5 months ago

Just chmod u+s sssd sshd vsftpd. This already requires CAP_SETUID for pod.

No u+s doesn't use CAP_SETUID just allowPrivilegeEscalation: true.

Maybe. But that way or another, without 'user-ns' support, 'u+s' means that your container process runs with 'uid=0' in the host namespace -- IIUC, this is something to be disallowed soon. And older versions of SSSD have a hard check for 'uid==0', so a game over right away.

We can run vsftpd/sshd without any capabilities/privileges assuming the above statement is true and setuid is avoided.

CAP_CHOWN, CAP_DAC_READ_SEARCH, CAP_FOWNER

These are generally required due to incorrect filesystem permissions.

Probably... mostly.

Are they still required with chmod -R 777 / ?? possibly the files being accessed would need to change

SSSD will refuse to start if, for example, sssd.conf is readable by all. There are might be other catches. But those tricks shouldn't be needed with sssd-2.10+ It's not available in official RHEL repos yet, but you could use https://copr.fedorainfracloud.org/coprs/g/sssd/nightly/ (currently Fedora rawhide , Centos-stream 9 and Rhel 9 packages there are built '--with-sssd-user=sssd', other with '=root', all flavors doesn't require any caps besides 3 helpers mentioned, but you can strip file caps after install). It would be nice if you could give it a try and provide your observations / feedback.

davidmather commented 5 months ago

It would be nice if you could give it a try and provide your observations / feedback.

Sure will take a look and get back to you. It will probably be next week as my working day is over.

davidmather commented 5 months ago

Hi @alexey-tikhonov

I am seeing sss_log.c has the following vsylog calls hardcode /dev/log which cannot be accessed without CAP_DAC_READ_SEARCH, CAP_FOWNER

Can the syslog calls be replaced with a port or file based logger?

#ifdef WITH_JOURNALD

static void sss_log_internal(int priority, int facility, const char *format,
                             va_list ap)
{
    int syslog_priority;
    int ret;
    char *message;
    const char *domain;

    ret = vasprintf(&message, format, ap);

    if (ret == -1) {
        /* ENOMEM */
        return;
    }

    domain = getenv(SSS_DOM_ENV);
    if (domain == NULL) {
        domain = "";
    }

    syslog_priority = sss_to_syslog(priority);
    sd_journal_send("MESSAGE=%s", message,
                    "SSSD_DOMAIN=%s", domain,
                    "SSSD_PRG_NAME=sssd[%s]", debug_prg_name,
                    "PRIORITY=%i", syslog_priority,
                    "SYSLOG_FACILITY=%i", LOG_FAC(facility),
                    NULL);

    free(message);
}

#else /* WITH_JOURNALD */

static void sss_log_internal(int priority, int facility, const char *format,
                            va_list ap)
{
    int syslog_priority = sss_to_syslog(priority);

    vsyslog(facility|syslog_priority, format, ap);
}

#endif /* WITH_JOURNALD */

There is also

#define ERROR(pamh, fmt, ...) do { \
    if (debug_enabled) { \
        pam_error(pamh, "pam_sss_gss: " fmt, ## __VA_ARGS__); \
        pam_syslog(pamh, LOG_ERR, fmt, ## __VA_ARGS__); \
    } \
} while (0)

in pam_sss_gss.c

alexey-tikhonov commented 5 months ago

I am seeing sss_log.c has the following vsylog calls hardcode /dev/log which cannot be accessed without CAP_DAC_READ_SEARCH, CAP_FOWNER

That's a great topic - what to do with logging in the container.

Historically SSSD has two log facilities: (1) https://github.com/SSSD/sssd/blob/0d5e8f11714e8e6cc0ad28e03fecf0f5732528b3/src/util/debug.h#L135 (2) https://github.com/SSSD/sssd/blob/0d5e8f11714e8e6cc0ad28e03fecf0f5732528b3/src/util/util.h#L184

(1) is used to "log everything" for debugging (for example, a tricky misconfiguration or a bug in SSSD). It can log to:

-- selected by '--logger' command line option of main 'sssd' process. It's typically set to 'files' (by default).

(2) is used to log most important notices to sysadmins, typically requiring immediate action (there are might be cases of misuse though) As you quoted, it can log to:

-- selected at build time by ./configure option '--with-syslog=syslog|journald' (not configurable at runtime) In builds I referenced (https://copr.fedorainfracloud.org/coprs/g/sssd/nightly/) it's configured --with-syslog=journald And this is most probably not something suitable in a container in general.

(2) is a tiny subset of (1)

I'm not fluent with containers, but IIUC typical approach is that app logs to stdout and then container runtime takes care of everything else. But this naturally also requires "single container - single app" approach.

The question is: what would be equivalent (if needed) for SYSLOG's LOG_CRIT/LOG_ALERT/SSS_LOG_EMERG in container use case?

One solution could be to introduce -with-syslog=none option (that would make sss_log() simply a no-op) and produce special builds of SSSD for in-container usage. I suspect there will be other tweaks in those builds anyway, like "do not try to store TGT in case krb5 auth".

davidmather commented 5 months ago

Hi @alexey-tikhonov

The question is: what would be equivalent (if needed) for SYSLOG's LOG_CRIT/LOG_ALERT/SSS_LOG_EMERG in container use case?

There are 3 main ways

  1. you can log to a different unix domain socket
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>

#define SOCKET_PATH "/var/run/mysocket" // Path to the Unix domain socket
#define MAX_MSG_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_un server_addr;
    char message[MAX_MSG_SIZE];
    openlog("MyProgram", LOG_PID, LOG_LOCAL0);

    // Create a Unix domain socket
    sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        syslog(LOG_ERR, "Error creating socket");
        exit(EXIT_FAILURE);
    }

    // Set up server address
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1);

    // Construct the log message
    snprintf(message, MAX_MSG_SIZE, "Test log message");

    // Send message to Unix domain socket
    if (sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        syslog(LOG_ERR, "Error sending message");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // Close socket
    close(sockfd);

    // Close syslog
    closelog();

    return 0;
}

syslog.conf

`module(
    load="imuxsock"
    SysSock.Use="on"
    SysSock.Name="/tmp/sock"
)`
  1. You can log directly to a syslog datagram port (this is useful if syslog is running in a sidecar)
`#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <syslog.h>

#define SYSLOG_PORT 5140
#define SYSLOG_HOST "127.0.0.1"

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <log_message>\n", argv[0]);
        return 1;
    }

    // Open syslog with desired facility
    openlog("MyProgram", LOG_PID, LOG_LOCAL0); // Change facility as needed

    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    int sockfd;
    struct sockaddr_in server_addr;

    // Create a socket
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("Failed to create socket");
        return 1;
    }

    // Set up the server address
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SYSLOG_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SYSLOG_HOST);

    // Log message
    char *message = NULL;
    size_t message_size = strlen(argv[1]) + 12;  // Include null terminator

    message = malloc(message_size);
    if (message == NULL) {
        perror("Failed to allocate memory");
        return 1;
    }
    snprintf(message, message_size, "<%d>%s", LOG_USER | LOG_INFO, argv[1]);

    // Send the message to the syslog server
    if (sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Failed to send message to syslog server");
    }

    close(sockfd); // Close the socket after sending the message

    return 0;
}
`

Syslog config

module(load="imudp") input(type="imudp" port="5140")

  1. You can log to a file with the syslog imfile module

Syslog config

`# Load Text File Input Module
module(load="imfile" PollingInterval="10") #needs to be done just once # Read the file MongoDB audit log input(type="imfile"
      File="/var/log/sssd.log"
      Tag="sssd:"
      Severity="info"
      Facility="local2"
      reopenOnTruncate="on"
      Ruleset="forward_to_remote")
`

Arguably version 2 is the best because the container can have a readOnlyRootFilesystem and syslog running in a sidecar in all cases logs can be pushed directly to elasticsearch. https://www.elastic.co/blog/openshift-container-logs-red-hat-logging-operator

Logging only to stdout/stderr is discouraged while "kubectl logs" will show the most recent logs for anything that could run for a long time there is a risk that the relevant logs will not be maintained if there is a lot of logs and it is difficult to get a coherent picture of a single applications logs since everything is writing to the one place.

alexey-tikhonov commented 5 months ago

Just a quick update: before touching 'syslog' based logger, I wanted to have a build that doesn't require 'systemd' stuff (ideally "unprivileged" container shouldn't have 'systemd' installed). Hence #7262 (#7268) But it's more tricky than I expected:

# ldd /lib64/libdbus-1.so.3
    libsystemd.so.0 => /lib64/libsystemd.so.0 (0x00007f542fd16000)

and SSSD uses 'libdbus' for implementation of own internal dbus server/clients (https://github.com/SSSD/sssd/tree/master/src/sbus)

alexey-tikhonov commented 3 months ago

@davidmather

Actually...

/dev/log which cannot be accessed without CAP_DAC_READ_SEARCH, CAP_FOWNER

Why? What/how is used as system logger in your case?

alexey-tikhonov commented 3 months ago

FWIW, I added '--with-syslog=stdout' build option in #7262

davidmather commented 3 months ago

Why? What/how is used as system logger in your case?

We have moved the system logger to /tmp/sock because the /dev/log socket requires root to create a socket in that folder on kubernetes but not /tmp.

in rsyslog.conf it looks like. module( load="imuxsock" SysSock.Use="on" SysSock.Name="/tmp/sock" )

Sorry for the late reply I am kept very busy.

alexey-tikhonov commented 3 months ago

because the /dev/log socket requires root to create a socket in that folder

Ah, so that's not about unprivileged SSSD accessing this socket (this shouldn't be an issue), but about socket creation itself.

"/dev/log" is hard coded in glibc: https://github.com/bminor/glibc/blob/992daa0b4b5fa8a9f403c9575638cec288e12bfa/bits/syslog-path.h#L26

But isn't it possible to create socket in advance while creating container image?

Anyway, does '--with-syslog=stdout' ./configure option (#7262) work for your use case?

alexey-tikhonov commented 1 month ago

Anyway, does '--with-syslog=stdout' ./configure option (#7262) work for your use case?

@davidmather , ping