Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sssd container support #5443

Open
holmanb opened this issue Dec 24, 2020 · 20 comments
Open

sssd container support #5443

holmanb opened this issue Dec 24, 2020 · 20 comments
Assignees

Comments

@holmanb
Copy link

holmanb commented Dec 24, 2020

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
Copy link
Member

alexey-tikhonov commented Mar 21, 2024

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)

@davidmather
Copy link

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
Copy link
Member

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
Copy link

davidmather commented Mar 22, 2024

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
Copy link
Member

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
Copy link

davidmather commented Mar 22, 2024

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
Copy link
Member

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:

  • either rely on eventual support of 'user-ns' by Openshift (then you should be able to run your existing container as is in fully restricted host namespace security context)
  • or re-design your container so it doesn't require any privileges/capabilities (in any namespace)

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:

%global child_capabilities cap_chown,cap_dac_override,cap_setuid,cap_setgid=ep

What base image do you use?

@davidmather
Copy link

davidmather commented Mar 22, 2024

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
Copy link
Member

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
Copy link

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
Copy link

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
Copy link
Member

alexey-tikhonov commented Mar 25, 2024

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)

#define DEBUG(level, format, ...) do { \

(2)
void sss_log(int priority, const char *format, ...) SSS_ATTRIBUTE_PRINTF(2, 3);

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

  • stderr
  • files (typically /var/log/sssd/*)
  • systemd journald (if support was built)

-- 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:

  • systemd journald
  • SYSLOG using vsyslog()

-- 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
Copy link

davidmather commented Mar 25, 2024

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
Copy link
Member

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
Copy link
Member

@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
Copy link
Member

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

@davidmather
Copy link

davidmather commented Jun 3, 2024

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
Copy link
Member

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
Copy link
Member

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

@davidmather , ping

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants