Wednesday, July 26, 2017

sudo and RBAC, or which privilege to pick

sudo and RBAC, or which privilege to pick

Robert Milkowski's recently posted how to use sudo with Solaris privileges, see Sudo and Solaris Privileges.

milek    ALL=()PRIVS="basic,sys_admin" NOPASSWD:/usr/sbin/fmadm faulty

Solaris 11.3 SRU 21 currently has 87 privileges (see ppriv -l. But why do I need "sys_admin" for fmadm?

Well the fmadm(1M) manpage says so. ;-)

The fmadm utility requires the user to possess the SYS_ADMIN privilege.

But how to check if we don't know which privilege is needed? Let's start with a small non-blackbox example.

$ cat p.c
#include <assert.h>
#include <priv.h>
#include <stdio.h>

int
main(void)
{
    priv_set_t *sp = priv_allocset();
    assert(sp != NULL);

    int ret = getppriv(PRIV_EFFECTIVE, sp);
    assert(ret == 0);

    if (!priv_ismember(sp, PRIV_SYS_ADMIN)) {
        printf("Nope\n");
    }

    priv_freeset(sp);
    return 0;
}

$ cc -m64 -g -Wall p.c

$ apptrace -v priv_ismember ./a.out
-> a.out    -> libc.so.1:boolean_t priv_ismember(const priv_set_t * = 0xffff80ffbf690290, const char * = 0x400cde "sys_admin")
        arg0 = (const priv_set_t *) 0xffff80ffbf690290
        arg1 = (const char *) 0x400cde "sys_admin"
Nope

When we try the same with fmadm faulty there are no priv_ismember calls. But we see a lot of door calls and we recall there's a fault manager daemon running.

$ svcs -p svc:/system/fmd:default
STATE          STIME    FMRI
online         Jul_19   svc:/system/fmd:default
               Jul_19        998 fmd

Let's fire up DTrace to check if there are any priv_ismember calls in /usr/lib/fm/fmd/fmd.

# cat priv.d
#!/usr/sbin/dtrace -Cs

#include <sys/priv_const.h>

#pragma D option quiet

pid$target::priv_ismember:entry
{
    trace(stringof(copyinstr(arg1)));
}

# ./priv.d -p 998

$ fmadm faulty
fmadm: failed to get case list from fmd: operation requires additional privilege

# ./priv.d -p 998
sys_admin

And there's our priv_ismember call checking for the "PRIV_SYS_ADMIN" privilege.

Links

  • privileges(5)
  • apptrace(1)

Friday, June 30, 2017

Periodic services with SMF

Periodic services with SMF

Solaris 11.3 extended SMF to support periodic and scheduled services. It was done mostly to ease IPS packagers because you can't just drop a file in /etc/cron.d and it will magically self-assemble to a cronjob (unlike e.g. /etc/logadm.d).

What's the difference between periodic and scheduled? You want a periodic service for tasks that have to run say every 15 minutes.

Each invocation of a periodic service instance start method occurs at a time relative to the last invocation.

And a scheduled service for tasks that have to run at a specific time.

Each invocation of a scheduled service instance start method occurs at a specific absolute time. Use a scheduled service when the task must run at a certain time, such as during off-peak hours.

The svcbundle command was extended as well to create periodic and scheduled service manifests.

For the periodic example we'll use fetchmail to check for new mails every 15 minutes (== 900s).

$ echo $(( 15 * 60 ))
900
$ svcbundle -o periodic_fetchmail.xml -s service-name=site/periodic/fetchmail \
  -s start-method='/usr/bin/fetchmail -s' -s period=900
# cp periodic_fetchmail.xml /lib/svc/manifest/site/
# svcadm restart svc:/system/manifest-import:default
$ svcs -o NRUN svc:/site/periodic/fetchmail:default
NRUN
22:15:27

We could also use a method_credential (see svc.periodicd(8)) so that the manifest runs as the specified user.

Let's create a scheduled service that runs every night around 00:00 o'clock now.

The crontab entry would look like the following.

0 0 * * * /usr/sbin/audit -n

Let's convert that to SMF with svcbundle.

$ svcbundle -o scheduled_auditrotate.xml -s service-name=site/scheduled/auditrotate \
  -s start-method='/usr/sbin/audit -n' \
  -s hour=0 -s minute=0 \
  -s interval=day
# cp scheduled_auditrotate.xml /lib/svc/manifest/site/
# svcadm restart svc:/system/manifest-import:default
$ svcs -o NRUN svc:/site/scheduled/auditrotate:default
NRUN
 0:00:51

We should edit the manifest and remove the dependency on vc:/milestone/multi-user and instead depend on svc:/system/auditd:default and fill in common_name and description.

For the last example we'll follow Oracle's advice and do a monthly scrub of our disks. See Recommended Storage Pool Practices.

Scrub your ZFS storage pools routinely, such as monthly, if you are using datacenter quality services.

Let's do another scheduled service which runs every month.

$ svcbundle -o scheduled_rpoolscrub.xml -s service-name=site/scheduled/rpoolscrub \
  -s start-method='/usr/sbin/zpool scrub rpool' \
  -s day_of_month=13 -s hour=4 \
  -s interval=month
# cp scheduled_rpoolscrub.xml /lib/svc/manifest/site/
# svcadm restart svc:/system/manifest-import:default

... wait till it executed

$ svcs -o LRUN svc:/site/scheduled/rpoolscrub:default
LRUN
 4:17:49
$ svcs -o NRUN svc:/site/scheduled/rpoolscrub:default
NRUN
Jul_13

Also note there are log files in /var/svc/log in case something goes wrong.

$ svcs -Lv site/scheduled/rpoolscrub
svc:/site/scheduled/rpoolscrub:default (Monthly rpool scrub)
Logfile not found for svc:/site/scheduled/rpoolscrub:default. Error: unknown error.

$ tail /var/svc/log/site-scheduled-rpoolscrub:default
Jun 13 04:17:49/6:Executing start method ("/usr/sbin/zpool scrub rpool")
Jun 13 04:17:55/5:Method "start" exited with status 0.

When you're an IPS packager, don't forget to mogrify your SMF manifests.

<transform dir path=lib/svc/manifest -> set group sys>
<transform file path=lib/svc/manifest -> set group sys>
<transform file path=lib/svc/method/.* -> set mode 0555>
<transform file path=(var|lib)/svc/manifest/.*\.xml$ -> \
    default restart_fmri svc:/system/manifest-import:default>

Links

Tuesday, June 13, 2017

How to build software on Solaris 11/SPARC

How to build software on Solaris 11/SPARC

Today we'll figure out the default build flags used by the Solaris Userland Consolidation.

We already used them while building nginx, see nginx on Solaris 11.3 SRU 19 with ECC crypto and HTTP/2 support.

We need a compiler before we can build anything. My preferred choice is the Solaris Developer Studio compiler. You can download a tarball at Developer Studio or request a solarisstudio repository certificate at Oracle Repositories.

Either way, you should have a decent compiler now.

$ /opt/developerstudio12.5/bin/cc -V
cc: Studio 12.5 Sun C 5.14 SunOS_sparc 2016/05/31

Good. Let get the default 64bit *FLAGS used to build software from shared-macros.mk.

# Enables large file support for components that have no other means of doing
# so.  Use CPP_LARGEFILES and not the .32/.64 variety directly
CPP_LARGEFILES.64 := $(shell getconf LFS64_CFLAGS)
CPP_LARGEFILES =  $(CPP_LARGEFILES.$(BITS))

# XPG6 mode.  This option enables XPG6 conformance, plus extensions.
# Amongst other things, this option will cause system calls like
# popen (3C) and system (3C) to invoke the standards-conforming
# shell, /usr/xpg4/bin/sh, instead of /usr/bin/sh.  Add studio_XPG6MODE to
# CFLAGS instead of using this directly
CPP_XPG6MODE= -D_XOPEN_SOURCE=600 -D__EXTENSIONS__=1 -D_XPG6

This should equal the following CPPFLAGS:

CPPFLAGS="$(getconf LFS64_CFLAGS) -D_XOPEN_SOURCE=600 -D__EXTENSIONS__=1 -D_XPG6"

Let's do the same for CFLAGS.

BITS ?=   64

MACH :=  $(shell uname -p)
MACH64_1 = $(MACH:sparc=sparcv9)

CC_BITS = -m$(BITS)

studio_XBITS.sparc.64 += -xarch=sparcvis -xchip=ultra2
studio_XBITS = $(studio_XBITS.$(MACH).$(BITS))

# Turn on recognition of supported C99 language features and enable the 1999 C
# standard library semantics of routines that appear in both the 1990 and
# 1999 C standard. To use set studio_C99MODE=$(studio_C99_ENABLE) in your
# component Makefile.
studio_C99_ENABLE =  -xc99=all

# Allow zero-sized struct/union declarations and void functions with return
# statements.
studio_FEATURES_EXTENSIONS = -features=extensions

studio_OPT.sparc.64 ?= -xO4
studio_OPT ?=  $(studio_OPT.$(MACH).$(BITS))

# Studio PIC code generation.  Use CC_PIC instead to select PIC code generation.
studio_PIC =  -KPIC -DPIC

# The Sun Studio 11 compiler has changed the behaviour of integer
# wrap arounds and so a flag is needed to use the legacy behaviour
# (without this flag panics/hangs could be exposed within the source).
# This is used through studio_IROPTS, not the 'sparc' variety.
studio_IROPTS.sparc = -W2,-xwrap_int
studio_IROPTS =  $(studio_IROPTS.$(MACH))

# Control register usage for generated code.  SPARC ABI requires system
# libraries not to use application registers.  x86 requires 'no%frameptr' at
# x04 or higher.

# We should just use -xregs but we need to workaround 7030022. Note
# that we can't use the (documented) -Wc,-xregs workaround because
# libtool really hates -Wc and thinks it should be -Wl. Instead
# we use an (undocumented) option which actually happens to be what
# CC would use.
studio_XREGS.sparc = -Qoption cg -xregs=no%appl
studio_XREGS =  $(studio_XREGS.$(MACH))

# Set data alignment on sparc to reasonable values, 8 byte alignment for 32 bit
# objects and 16 byte alignment for 64 bit objects.  This is added to CFLAGS by
# default.
studio_ALIGN.sparc.64 = -xmemalign=16s
studio_ALIGN =  $(studio_ALIGN.$(MACH).$(BITS))

# Studio shorthand for building multi-threaded code,  enables -D_REENTRANT and
# linking with threadin support.  This is added to CFLAGS by default, override
# studio_MT to turn this off.
studio_MT =  -mt

CFLAGS.studio += $(studio_OPT) $(studio_XBITS) $(studio_XREGS) \
   $(studio_IROPTS) $(studio_C99MODE) $(studio_ALIGN) \
   $(studio_MT)

This should equal the following CFLAGS:

CFLAGS="-m64 -xO4 -xarch=sparcvis -xchip=ultra2 \
  -Qoption cg -xregs=no%appl -W2,-xwrap_int -xc99=all -xmemalign=16s \
  -mt -KPIC -DPIC"

And last but not least, for LDFLAGS.

# set the bittedness that we want to link
LD_BITS = -$(BITS)

# eliminate unreferenced dynamic dependencies
LD_Z_IGNORE =  -zignore

# eliminate comments
LD_Z_STRIP_CLASS = -zstrip-class=comment

# use direct binding
LD_B_DIRECT =  -Bdirect

# build a PIE binary
# to enable creating a PIE binary, add LD_Z_PIE_MODE = $(LD_Z_PIE_ENABLE)
# to the component makefile, and ensure that it's built PIC (CC_PIC_ENABLE).
LD_Z_PIE_ENABLE = -ztype=pie

# by default, turn on Address Space Layout Randomization, non-executable
# stack and non-executable heap for ELF executables;
ASLR_ENABLE =    -zaslr=enable
NXSTACK_ENABLE =  -znxstack=enable
NXHEAP_ENABLE =   -znxheap=enable

# Create a non-executable bss segment when linking.
LD_MAP_NOEXBSS.sparc = -M /usr/lib/ld/map.noexbss

# Create a non-executable data segment when linking.  Due to PLT needs, the
# data segment must be executable on sparc, but the bss does not.
# see mapfile comments for more information
LD_MAP_NOEXDATA.sparc = $(LD_MAP_NOEXBSS.$(MACH))

# Page alignment
LD_MAP_PAGEALIGN = -M /usr/lib/ld/map.pagealign

# Default linker options that everyone should get.  Do not add additional
# libraries to this macro, as it will apply to everything linked during the
# component build.
LD_OPTIONS += $(LD_MAP_NOEXDATA.$(MACH)) \
  $(LD_MAP_PAGEALIGN) $(LD_B_DIRECT) $(LD_Z_IGNORE) \
  $(LD_Z_STRIP_CLASS)

This should equal the following LDFLAGS:

LDFLAGS="-m64 -M /usr/lib/ld/map.noexbss \
  -M /usr/lib/ld/map.pagealign -Bdirect -zignore \
  -zstrip-class=comment -ztype=pie \
  -zaslr=enable -znxstack=enable -znxheap=enable"

Some software also doesn't like the Solaris nm, so we'll use GNU nm instead. See configure.mk.

# temporarily work around some issues
CONFIGURE_ENV += "ac_cv_func_realloc_0_nonnull=yes"
CONFIGURE_ENV += "NM=/usr/gnu/bin/nm"

Putting everything together, here is an example of how I usually invoke configure when building FOSS:

$ getconf PATH
/usr/xpg6/bin:/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/developerstudio12.5/bin:...
$ PATH=$(getconf PATH) ./configure PKG_CONFIG_PATH=/usr/lib/64/pkgconfig NM=/usr/gnu/bin/nm SHELL=bash MAKE=gmake \
  CPPFLAGS="$(getconf LFS64_CFLAGS) -D_XOPEN_SOURCE=600 -D__EXTENSIONS__=1 -D_XPG6" \
  CC=cc CFLAGS='-m64 -xO4 -xarch=sparcvis2 -Qoption cg -xregs=no%appl -W2,-xwrap_int \
    -xc99=all -xmemalign=16s -mt -KPIC -DPIC' \
  LDFLAGS='-m64 -M /usr/lib/ld/map.noexbss -M /usr/lib/ld/map.pagealign \
     -zaslr=enable -znxstack=enable -znxheap=enable \
     -Bdirect -zignore -zstrip-class=comment -ztype=pie' \
   --prefix=/opt/local ...
$ PATH=$(getconf PATH) gmake
...

Links

Tuesday, May 23, 2017

They joy of replacing a local disk with SVM

They joy of replacing a local disk with SVM

We still have some old Sun Fire V245 server here and I had the pleasure to replace a failed disk today.

The server is still running Solaris 10 and using SVM to mirror the root disks.

What's the failed disk in question?

# iostat -En
c0t0d0           Soft Errors: 3039 Hard Errors: 75 Transport Errors: 14
Vendor: FUJITSU  Product: MAY2073RCSUN72G  Revision: 0501 Serial No: xxxxxxxxxx
Size: 73.41GB <73407865856 bytes>
Media Error: 64 Device Not Ready: 0 No Device: 11 Recoverable: 3039
Illegal Request: 2 Predictive Failure Analysis: 12

Nasty, let's configure it out.

# disk=c0t0d0
# metastat -p > /etc/lvm/md.tab
# grep $disk /etc/lvm/md.tab
d21 1 1 c0t0d0s1
d11 1 1 c0t0d0s0
# metadetach d10 d11
d10: submirror d11 is detached
# metadetach d20 d21
metadetach: solaris: d20: attempt an operation on a submirror that has erred components

Ooops, I hope the force is still with me...

# metastat d20
d20: Mirror
    Submirror 0: d21
      State: Needs maintenance
    Submirror 1: d22
      State: Okay
...
# metadetach -f d20 d21
d20: submirror d21 is detached

I had such anger, but it's all good now. Let's continue.

# metaclear d11
d11: Concat/Stripe is cleared
# metaclear d21
d11: Concat/Stripe is cleared
...
# metadb | grep $disk
     a m  p  luo        16              8192            /dev/dsk/c0t0d0s7
     a    p  luo        8208            8192            /dev/dsk/c0t0d0s7
     a    p  luo        16400           8192            /dev/dsk/c0t0d0s7
# metadb -d ${disk}s7
# cfgadm -al | grep $disk
c0::dsk/c0t0d0                 disk         connected    configured   unknown
# cfgadm -c unconfigure c0::dsk/c0t0d0

Now we can physically replace the failed disk.

# tail -f /var/adm/messages
...
May 23 12:30:20 solaris genunix: [ID 408114 kern.info] /pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1/sd@0,0 (sd0) offline
May 23 12:30:27 solaris scsi: [ID 107833 kern.warning] WARNING: /pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1 (mpt0):
May 23 12:30:27 solaris    mpt_handle_event_sync : SAS target 0 added.
May 23 12:30:27 solaris scsi: [ID 583861 kern.info] sd0 at mpt0: unit-address 0,0: target 0 lun 0
May 23 12:30:27 solaris genunix: [ID 936769 kern.info] sd0 is /pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1/sd@0,0
May 23 12:30:28 solaris scsi: [ID 107833 kern.warning] WARNING: /pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1/sd@0,0 (sd0):
May 23 12:30:28 solaris    Corrupt label - label checksum failed
May 23 12:30:28 solaris genunix: [ID 408114 kern.info] /pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1/sd@0,0 (sd0) online

Alright, let's configure the new disk in.

# cfgadm -c configure c0::dsk/c0t0d0
# format $disk

c0t0d0: configured with capacity of 68.35GB
selecting c0t0d0
[disk formatted]
...
format> label
Ready to label disk, continue? y

format> quit

Time to rebuild our SVM mirror.

# metastat d20
...
Device Relocation Information:
Device   Reloc  Device ID
c0t1d0   Yes    id1,sd@n500000e016af27c0

# sourcedisk=c0t1d0
# prtvtoc /dev/rdsk/${sourcedisk}s2 | fmthard -s - /dev/rdsk/${disk}s2
# metadb -a -c3 ${disk}s7
# metainit d11
# metainit d21
# metattach d10 d11
d10: submirror d11 is attached
# metattach d20 d21
d20: submirror d21 is attached
# metadevadm -u $disk
Updating Solaris Volume Manager device relocation information for c0t0d0
Old device reloc information:
        id1,sd@n500000e0135e2dd0
New device reloc information:
        id1,sd@n500000e0135e2dd0

# installboot /usr/platform/$(uname -i)/lib/fs/ufs/bootblk /dev/rdsk/${disk}s0

# metastat -c
d20              m   4.0GB d22 d21 (resync-1%)
    d22          s   4.0GB c0t1d0s1
    d21          s   4.0GB c0t0d0s1

Once the resync is done we have our OS disks mirrored again.

Links

Thursday, May 11, 2017

Ansible 2.3 on Solaris 11.3

Ansible 2.3 on Solaris 11.3

Let's automate some tasks we do all the time.

Yes I know, I could use Puppet, but the Puppet version bundled with Solaris 11.3 is rather old (3.6.2) and some modules are broken (e.g. "ldap provider always finds authentication_method out of sync (Bug 22166490)"). So we'll use Ansible instead.

$ wget http://releases.ansible.com/ansible/ansible-2.3.1.0.tar.gz

# cd /opt
# gzcat .../ansible-2.3.1.0.tar.gz | tar xf -
# cat ansible-2.3.1.0/requirements.txt
...
jinja2
PyYAML
paramiko
pycrypto >= 2.6
setuptools

Seems like we need some Python modules to get Ansible working. Let's install them.

# pkg install --no-backup-be jinja2 pyyaml setuptools
           Packages to install: 22
...

We don't need paramiko and pycrypto (we'll use SSH instead), see Replace PyCrypto usage with cryptography.io #13075.

To speed things up we need an SSH client that supports ControlPersist. So let's install OpenSSH as well and make it the default.

# pkg install --no-backup-be network/openssh
           Packages to install:  1
...
# pkg set-mediator --no-backup-be -I openssh ssh
            Packages to change:  3
...

Does it work?

# PYTHONPATH=/opt/ansible-2.3.1.0/lib /opt/ansible-2.3.1.0/bin/ansible --version
ansible 2.3.1.0
  config file =
  configured module search path = Default w/o overrides
  python version = 2.7.9 (default, Dec  1 2016, 10:32:39) [C]

# PYTHONPATH=/opt/ansible-2.3.1.0/lib /opt/ansible-2.3.1.0/bin/ansible localhost -m ping
 [WARNING]: Host file not found: /etc/ansible/hosts

 [WARNING]: provided hosts list is empty, only localhost is available

localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Good. Time to write our first Playbook...

Links

Monday, May 8, 2017

FreeBSD aesni(4) and openssl

FreeBSD aesni(4) and openssl

I have to admit, I also like FreeBSD. There was a question if you need to kldload aesni to speed up openssl (or any application that's using libcrypto) and the short answer is no. The long answer...

What is AES-NI again?

The new AES-NI instruction set is comprised of six new instructions that perform several compute intensive parts of the AES algorithm. These instructions can execute using significantly less clock cycles than a software solution.

So AES-NI is basically just another mnemonic like ADD, SUB, XOR, MOV, AND, etc. You can just call them from user space. And that's what OpenSSL/LibreSSL does, see aesni-x86_64.S.

.globl aesni_cbc_encrypt
...
aesni_cbc_encrypt:
...
.byte 102,15,56,220,209
...

And there's our AESENC opcode. It's in .bytes notation because FreeBSD is still using a GPLv2 binutils that's too old for AES-NI mnemonics.

In Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2 we see that the AESENC instruction has the following opcode.

66 0F 38 DC /r
AESENC xmm1, xmm2/m128

So ".byte 102,15,56,220,209" translates with some decimal to hexadecimal conversion to "0x66, 0x0F, 0x38, 0xDC". Which is just the opcode for AESENC above.

So there is no kernel stuff involved. What is aesni(4) used for then?

The aesni driver registers itself to accelerate AES operations for crypto(4).

In sys/crypto/aesni/aesni.c we see that the AES-NI kernel module registers itself as being hardware capable and for the following ciphers (see sys/crypto/aesni/aesni.c and crypto(9)).

static int
aesni_attach(device_t dev)
{
 struct aesni_softc *sc;
...
 sc->cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE |
     CRYPTOCAP_F_SYNC);
...
 crypto_register(sc->cid, CRYPTO_AES_CBC, 0, 0);
 crypto_register(sc->cid, CRYPTO_AES_ICM, 0, 0);
 crypto_register(sc->cid, CRYPTO_AES_NIST_GCM_16, 0, 0);
 crypto_register(sc->cid, CRYPTO_AES_128_NIST_GMAC, 0, 0);
 crypto_register(sc->cid, CRYPTO_AES_192_NIST_GMAC, 0, 0);
 crypto_register(sc->cid, CRYPTO_AES_256_NIST_GMAC, 0, 0);
 crypto_register(sc->cid, CRYPTO_AES_XTS, 0, 0);
...

So the aesni kernel module provides crypto services with the OpenCrypto framework for both user space (that's the /dev/crypto device) via crypto(4) and kernel space (think of GELI and IPSec) via crypto(9).

Still not convinced that openssl is not using aesni(4)? Let's fire up DTrace just to be sure...

For the first test, no aesni(4) kernel module is loaded. We use openssl with -evp to make sure we're actually using hardware crypto (and you'll see it's calling libcrypto's aesni_cbc_encrypt function we talked about earlier). Notice there is almost no user/kernel space boundary crossing.

# kldstat 
Id Refs Address            Size     Name
 1    6 0xffffffff80200000 1fa7c38  kernel
 2    1 0xffffffff82219000 249d     ulpt.ko
 3    1 0xffffffff8221c000 adec     tmpfs.ko

# kldload dtraceall

# dtrace -n 'pid$target:libcrypto.so.8:*aesni*:entry { @[probefunc] = count(); }' \
  -c "openssl speed -elapsed -evp aes-128-cbc"
...
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
aes-128-cbc       5973.14k    23210.84k    84090.94k   238951.75k   543361.71k
...
  aesni_cbc_encrypt                                           4105425

# dtrace -n 'fbt:kernel:copy*:entry /pid == $target/ { @bytes[probefunc] = quantize(arg2); }' \
  -c "openssl speed -elapsed -evp aes-128-cbc"
...
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
aes-128-cbc     602153.10k   640760.18k   643890.94k   660515.73k   666079.99k
...
  copyin                                            
           value  ------------- Distribution ------------- count    
               4 |                                         0        
               8 |@                                        2        
              16 |@@@@@@@@@@@@                             16       
              32 |@@@@@@@@@@@@@@@@                         22       
              64 |@@@                                      4        
             128 |                                         0        
             256 |@@@@                                     5        
             512 |@@@@                                     5        
            1024 |                                         0        

  copyinstr                                         
           value  ------------- Distribution ------------- count    
             512 |                                         0        
            1024 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 6        
            2048 |                                         0        

  copyout                                           
           value  ------------- Distribution ------------- count    
               4 |                                         0        
               8 |@                                        1        
              16 |@@@@@@@@@                                15       
              32 |@@@@@@@@                                 14       
              64 |@                                        2        
             128 |@@@@@@@@@@@@                             21       
             256 |@@@                                      5        
             512 |@@@                                      6        
            1024 |                                         0        
            2048 |@@@                                      5        
            4096 |                                         0      

Let's load the aesni(4) kernel module now and check if any kernel aesni probes fire.

# kldload aesni
aesni0: <AES-CBC,AES-XTS,AES-GCM,AES-ICM> on motherboard

# dtrace -n 'fbt:aesni::entry /pid == $target/ { @[probefunc] = count(); }' \
  -c "openssl speed -elapsed -evp aes-128-cbc"
...
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
aes-128-cbc     616989.41k   668602.69k   670494.73k   673865.32k   679105.88k
...

No probes fired. That means openssl is not using the aesni kernel functions at all.

BUT, we can make openssl use aesni(4) with -engine cryptodev. Let's check if any kernel aesni and user/kernel space boundary crossing probes fire now.

# kldload cryptodev
# openssl engine -c -tt
(cryptodev) BSD cryptodev engine
 [RSA, DSA, DH, AES-128-CBC, AES-192-CBC, AES-256-CBC]
     [ available ]
...

# dtrace -n 'fbt:aesni::entry /pid == $target/ { @[probefunc] = count(); }' \
  -c "openssl speed -elapsed -evp aes-128-cbc"
...
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
aes-128-cbc       4056.66k    15608.91k    57565.04k   183731.20k   492147.10k
...
  aesni_cipher_setup_common                                         8
  aesni_freesession                                                 8
  aesni_newsession                                                  8
  aesni_cipher_alloc                                          3036256
  aesni_encrypt_cbc                                           3036256
  aesni_process                                               3036256

# dtrace -n 'fbt:kernel:copy*:entry /pid == $target/ { @bytes[probefunc] = quantize(arg2); }' \
  -c "openssl speed -elapsed -evp aes-128-cbc"
...
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
aes-128-cbc       3602.78k    13827.67k    51851.57k   168562.00k   472572.78k
...
  copyinstr                                         
           value  ------------- Distribution ------------- count    
             512 |                                         0        
            1024 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 6        
            2048 |                                         0        

  copyout                                           
           value  ------------- Distribution ------------- count    
               2 |                                         0        
               4 |                                         8        
               8 |                                         1        
              16 |@@@@@                                    675536   
              32 |@@@@@@@@@@@@@@@@@@@@                     2603253  
              64 |@@@@@                                    649862   
             128 |                                         21       
             256 |@@@@@                                    609223   
             512 |                                         6        
            1024 |@@@@                                     495120   
            2048 |                                         5        
            4096 |                                         0        
            8192 |@                                        173512   
           16384 |                                         0        

  copyin                                            
           value  ------------- Distribution ------------- count    
               2 |                                         0        
               4 |                                         15       
               8 |                                         3        
              16 |@@@@@@@@@@@@@@@@@                        3278781  
              32 |@@@@@@@@@@@@@                            2603265  
              64 |@@@                                      649864   
             128 |                                         0        
             256 |@@@                                      609223   
             512 |                                         5        
            1024 |@@@                                      495120   
            2048 |                                         0        
            4096 |                                         0        
            8192 |@                                        173512   
           16384 |                                         0  

That's weird, -engine cryptodev seems to be on by default as soon as we loaded the cryptodev kernel module. Also note the huge amount of user/kernel space boundary crossing. That's a lot of data to be copied from user space to kernel space and back again for nothing. Mental note here, don't load the cryptodev kernel module ever unless using a hifn(4), safe(4) or ubsec(4) crypto accelerator.

Links

Tuesday, May 2, 2017

AI install server using a https IPS repo

AI install server using a https IPS repo

Last time we created a local IPS repository (see https://crc32c.blogspot.de/2017/04/https-ips-repository-using-pkgdepotd.html) and added the latest SRU to it (see https://crc32c.blogspot.de/2017/04/how-to-add-sru-to-local-ips-repository.html).

Now it's time to create an AI install server, add some customizations and netboot/netinstall our first server.

# zfs create tank/install/auto_install
# zfs create tank/install/webserver_files

# pkg install --no-backup-be install/installadm

# cp /etc/certs/CA/UNIX_Dep_CA.pem /install/webserver_files/
# chown webservd:webservd /install/webserver_files/UNIX_Dep_CA.pem

# svccfg -s svc:/system/install/server:default
svc:/system/install/server:default> setprop all_services/default_imagepath_basedir = /install/auto_install
svc:/system/install/server:default> setprop all_services/enable_webui = false
svc:/system/install/server:default> setprop all_services/manage_dhcp = false
svc:/system/install/server:default> setprop all_services/webserver_files_dir = /install/webserver_files
svc:/system/install/server:default> refresh
svc:/system/install/server:default> ^D

# svcadm enable svc:/system/install/server:default

# installadm create-service -n solaris11_3-sparc -p solaris=https://pkg.mycompany.com/solaris/
OK to use subdir of /install/auto_install to store image? [y|N]: y
...
100% : Created Service: 'solaris11_3-sparc'
...

Good, now let's edit/create the manifest and system configuration profile.

The AI_HOSTNAME, AI_IPV4, etc. variables are resolved using data supplied by our dhcpd server we'll setup in a few.

# installadm export -n solaris11_3-sparc -m orig_default -o orig_default
# cat orig_default
...
      <source>
        <publisher name="solaris">
          <origin name="https://pkg.mycompany.com/solaris/"/>
          <credentials>
            <ca_cert src="http://pkg.mycompany.com:5555/files/UNIX_Dep_CA.pem"/>
          </credentials>
        </publisher>
      </source>
...

# installadm update-manifest -n solaris11_3-sparc -f ./orig_default
Changed Manifest: 'orig_default'

# sysconfig create-profile -o sc
# cat sc/sc_profile.xml
...
  <service version="1" type="service" name="system/identity">
    <instance enabled="true" name="node">
      <property_group type="application" name="config">
        <propval type="astring" name="nodename" value="{{AI_HOSTNAME}}"/>
      </property_group>
    </instance>
  </service>

  <service version="1" type="service" name="network/install">
    <instance enabled="true" name="default">
      <property_group type="application" name="install_ipv4_interface">
        <propval type="net_address_v4" name="static_address" value="{{AI_IPV4}}/{{AI_IPV4_PREFIXLEN}}"/>
        <propval type="astring" name="name" value="{{AI_NETLINK_VANITY}}/v4"/>
        <propval type="astring" name="address_type" value="static"/>
        <propval type="net_address_v4" name="default_route" value="{{AI_ROUTER}}"/>
      </property_group>
    </instance>
  </service>
...
  <service version="1" type="service" name="system/ocm">
    <instance enabled="false" name="default">
      <property_group type="application" name="reg">
        <propval type="astring" name="opt_out" value="true"/>
      </property_group>
    </instance>
  </service>
...

# installadm create-profile -n solaris11_3-sparc -f sc/sc_profile.xml -p custom

Almost done with the AI part. Let's create our first client.

# installadm create-client -e 00:11:22:33:44:55 -n solaris11_3-sparc

And that's it. Now we need an DHCP server to assign hostnames, DNS server, IP addresses, etc. for netbooting.

# cat << EOF > /etc/inet/dhcpd4.conf
authoritative;
log-facility local7;

option domain-name "mycompany.com";
option domain-name-servers 10.74.0.53, 10.74.5.3, 10.74.53.53;
option domain-search "mycompany.com", "lab.mycompany.com";

deny unknown-clients;

class "SPARC" {
  match if substring (option vendor-class-identifier, 0, 5) = "SUNW.";
  filename "http://pkg.mycompany.com:5555/cgi-bin/wanboot-cgi";
}

subnet 10.79.85.0 netmask 255.255.255.128 {
  option routers 10.79.85.1;
  option broadcast-address 10.79.85.127;
  option ntp-servers 10.79.85.1;
  next-server pkg.mycompany.com;
  use-host-decl-names on;
}

host ldg1 {
  hardware ethernet 00:11:22:33:44:55;
  fixed-address 10.79.85.101;
}
EOF

# chgrp sys /etc/inet/dhcpd4.conf
# /usr/lib/inet/dhcpd -t -cf /etc/inet/dhcpd4.conf

# printf "local7.debug\t\t\t\t\t/var/log/dhcpd.log\n" >> /etc/syslog.conf
# touch /var/log/dhcpd.log
# chgrp sys /var/log/dhcpd.log
# svcadm restart svc:/system/system-log:default

# echo "/var/log/dhcpd.log -C 4 -a '/usr/sbin/svccfg -s svc:/system/system-log:default refresh'" > /etc/logadm.d/dhcpd.logadm.conf
# chmod 444 /etc/logadm.d/dhcpd.logadm.conf
# chgrp sys /etc/logadm.d/dhcpd.logadm.conf
# svcadm refresh svc:/system/logadm-upgrade:default

# svcadm enable svc:/network/dhcp/server:ipv4

Time to install our first client.

{0} ok boot net:dhcp - install
...
13:13:33    Saving credential file UNIX_Dep_CA.pem
13:13:34    Creating the CA certificate symbolic link(s)
...
13:14:23    Installing packages from:
13:14:23        solaris
13:14:23            origin:  https://pkg.mycompany.com/solaris/
...
Automated Installation finished successfully

Good bye text-install ISOs...

Links

389 Directory Server 1.3.x LDAP client authentication

389 Directory Server 1.3.x LDAP client authentication Last time we did a multi-master replication setup, see 389 Directory Server 1.3.x Repl...