Najczęściej brakujące sterowniki dla Windows Server 2019 w serwerach Fujitsu PRIMERGY z generacji M5

Przeczytasz to w: 2 minut
Tak to wygląda, gdy jest już po wszystkim.

Niestety ten problem pojawia się często i niestety aplikacja do automatycznego instalowania sterowników nie daje rady (z opowieści klientów, nigdy z niej nie korzystałem ani nie chciałem). Tak czy siak rozwiązanie ogranicza się do pobrania sterowników ze strony producenta. Problem, który przedstawiam dotyczy PRIMERGY RX2540 M5, ale prawdopodobnie te same komponenty są w innych modelach. Najczęściej brakujące sterowniki to te, które widać w zrzucie ekranu poniżej:

Po wyszukaniu tych Device ID w sieci znalazłem odpowiedź na problemy. Należy pobrać następujące instalatory:

  • Applications > SATA RAID > Intel® C620 Chipset (SATA RAID) (Onboard on D3386-B1x) > ServerView RAID Manager (Windows, 64-bit),
  • Drivers > SATA RAID > Intel® C620 Chipset (SATA RAID) (Onboard on D3386-B1x) > PRAID AS200i: Driver for Windows Server 2019, WHQL certified
  • Drivers > Server Management Controller > iRMC S5 High-speed Transfer Interface (Onboard on D3386-B1x) > ServerView iRMC HighspeedTransferInterface

Wygląda to tak:

Potem wystarczy zainstalować i pobrać sterowniki z usługi Windows Update. Po tym wszystkie sterowniki będą działać poprawnie.

IMAPsync czyli zbawienie dla migracji serwerów pocztowych oraz kilka słów dlaczego nie warto korzystać z poczty Onetu i WP.pl

Przeczytasz to w: 23 minut

Czasami zdarza się taki moment, że nas serwer jest za stary, by go migrować i trzeba jakoś przenieść serwer, czasami admini chcą zmienić serwer pocztowy na jakieś inne rozwiązanie typu przenieść się na serwer Exchange z Postfix/Dovecot, lub po prostu zmienić dostawcę pocztowego, bo ileż można dostawać spam od Onetu czy WP? Poza takimi błahostkami jak przeniesienie prywatnej skrzynki pocztowej te narzędzie pozwala na masowe przenoszenie skrzynek. Jedyny minus rozwiązania jest taki, że trzeba zresetować wszystkim hasła na czas migracji.

Postaram się pokazać kilka scenariuszy przenoszenia skrzynek, przy czym w dużej mierze początkowa instalacja zawsze jest taka sama – jedyna różnica jest w ustawieniach programu. IMAPsync jest aplikacją, która zadziała na Windowsie i Linuksie, ale szczerze powiedziawszy miałem problem z jej działaniem spod Windowsa, więc używam Linuksa do operacji na nim. W przypadku posiadania Windowsa używam Linux Subsystem for Windows (WSL), bo dzięki temu na tym samym hoście można korzystać na wybranej dystrybucji Linuksa bez jakichkolwiek problemów.

Pierwszą rzeczą, którą należy zrobić jest włączenie funkcji w Windows 10/Windows Server 2016/Windows Server 2019:

Następnie, w przypadku Windows 10 znajdujemy w Microsoft Store aplikację o nazwie Ubuntu 18.04 (miałem problemy z działaniem IMAPsync na 20.04, prawdopodobnie ze względu na inną wersję OpenSSL) i ją instalujemy:

W Windowsie Server jest o tyle inaczej, że nie ma tam Microsoft Store. Taką paczkę należy pobrać z Internetu i zmienić jej format na .zip, bo w rzeczywistości to jest archiwum. Całość jest opisana w tym dokumencie. Na wypadek, gdyby zniknął, ściągamy z tego linku plik.

Zanim odpalimy aplikację, musimy uruchomić system ponownie. Jeśli tego nie zrobimy, najpewniej zobaczymy ten błąd:

W przypadku Windows Server należy odpalić aplikację ubuntu1804.exe, która jest wewnątrz rozpakowanego archiwum.

Po restarcie należy zdefiniować konto użytkownika i hasło:

Po tym należy wykonać polecenia, aby zainstalować IMAPsynca:

sudo apt update
sudo apt install libauthen-ntlm-perl libclass-load-perl libcrypt-ssleay-perl libdata-uniqid-perl libdigest-hmac-perl libdist-checkconflicts-perl \
libencode-imaputf7-perl libfile-copy-recursive-perl libfile-tail-perl libio-compress-perl libio-socket-inet6-perl libio-socket-ssl-perl libio-tee-perl \
libmail-imapclient-perl libmodule-scandeps-perl libnet-dbus-perl libnet-ssleay-perl libpar-packer-perl libreadonly-perl libregexp-common-perl \
libsys-meminfo-perl libterm-readkey-perl libtest-fatal-perl libtest-mock-guard-perl libtest-mockobject-perl libtest-pod-perl libtest-requires-perl \
libtest-simple-perl libunicode-string-perl liburi-perl libtest-nowarnings-perl libtest-deep-perl libtest-warn-perl make cpanminus apt-file libcrypt-openssl-rsa-perl libjson-webtoken-perl libcrypt-openssl-bignum-perl libcgi-pm-perl
sudo cpanm CGI
git clone https://github.com/imapsync/imapsync
cd imapsync/INSTALL.d
sudo ./prerequisites_imapsync

Jeśli wynik jest następujący – powinniśmy dostać mniej więcej następujący wynik:

supra@supra-pc:~/imapsync/INSTALL.d$ sudo ./prerequisites_imapsync
$SHELL says  /bin/bash
$0 gives  ./prerequisites_imapsync
ps -ef gives root     15542 15541  0 10:42 tty1     00:00:00 /bin/sh ./prerequisites_imapsync
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.4 LTS
Release:        18.04
Codename:       bionic
Linux supra-pc 4.4.0-19041-Microsoft #1-Microsoft Fri Dec 06 14:06:00 PST 2019 x86_64 x86_64 x86_64 GNU/Linux
Ok: Found Perl 5.26.1
make: Nothing to be done for 'foo'.
Ok: Found make GNU Make 4.1
Ok: Found Perl module App::cpanminus
Ok: Found Perl module Authen::NTLM
Ok: Found Perl module CGI
Ok: Found Perl module Compress::Zlib
Ok: Found Perl module Crypt::OpenSSL::RSA
Ok: Found Perl module Data::Dumper
Ok: Found Perl module Data::Uniqid
Ok: Found Perl module Digest::HMAC
Ok: Found Perl module Digest::HMAC_MD5
Ok: Found Perl module Digest::MD5
Ok: Found Perl module Dist::CheckConflicts
Ok: Found Perl module Encode
Ok: Found Perl module Encode::Byte
Ok: Found Perl module Encode::IMAPUTF7
Ok: Found Perl module File::Copy::Recursive
Ok: Found Perl module File::Tail
Ok: Found Perl module IO::Socket::INET
Ok: Found Perl module IO::Socket::INET6
Ok: Found Perl module IO::Socket::SSL
Ok: Found Perl module IO::Tee
Ok: Found Perl module JSON
Ok: Found Perl module JSON::WebToken
Ok: Found Perl module JSON::WebToken::Crypt::RSA
Ok: Found Perl module HTML::Entities
Ok: Found Perl module LWP::UserAgent
Ok: Found Perl module Mail::IMAPClient
Ok: Found Perl module MIME::Base64
Ok: Found Perl module Module::Implementation
Ok: Found Perl module Module::Runtime
Ok: Found Perl module Module::ScanDeps
Ok: Found Perl module Net::SSLeay
Ok: Found Perl module Package::Stash
Ok: Found Perl module Package::Stash::XS
Ok: Found Perl module PAR::Packer
Ok: Found Perl module Parse::RecDescent
Ok: Found Perl module Pod::Usage
Ok: Found Perl module Readonly
Ok: Found Perl module Regexp::Common
Ok: Found Perl module Sys::MemInfo
Ok: Found Perl module Term::ReadKey
Ok: Found Perl module Test::Fatal
Ok: Found Perl module Test::Mock::Guard
Ok: Found Perl module Test::MockObject
Ok: Found Perl module Test::More
Ok: Found Perl module Test::Pod
Ok: Found Perl module Test::Requires
Ok: Found Perl module Test::Deep
Ok: Found Perl module Text::ParseWords
Ok: Found Perl module Try::Tiny
Ok: Found Perl module Unicode::String
Ok: Found Perl module URI::Escape
All needed modules are already installed
Ok: Found cpanm cpanm (App::cpanminus) version 1.7043 (/usr/bin/cpanm)

Mając to można wrócić do głównego katalogu sklonowanego repozytorium Gita i zanim odpalimy IMAPsync warto sprawdzić dane do serwera pocztowego. Aby wykonać synchronizację, należy podać dane skrzynki, z której synchronizujemy wiadomości:

  • adres serwera pocztowego (opcja --host1),
  • port serwera pocztowego (opcja --port1, często opcjonalne, bo IMAPsync w przypadku prawidłowo zdefiniowanych wpisów w DNS sam wykryje odpowiedni port),
  • nazwa konta użytkownika (opcja --user1),
  • hasło konta użytkownika (opcja --password1),
  • wymuszenie wykorzystywania SSL (opcja --ssl1).

To samo podajemy dla docelowego serwera i użytkownika, lecz wykorzystujemy parametry z numerkiem 2 na końcu (np. --host2).

Wcześniej warto sprawdzić na jakim porcie serwer pocztowy nasłuchuje. Poniżej wykonuję test dla serwera OVH, to znaczy ssl0.ovh.net:

supra@supra-pc:/mnt/r/supra/Pobrane/imapsync-imapsync-1.945$ openssl s_client -connect ssl0.ovh.net:993 --showcerts -servername ssl0.ovh.net
CONNECTED(00000003)
depth=2 C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
verify return:1
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
verify return:1
depth=0 CN = ssl0.ovh.net
verify return:1
---
Certificate chain
 0 s:CN = ssl0.ovh.net
   i:C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
-----BEGIN CERTIFICATE-----
MIIGujCCBaKgAwIBAgIRAKNd5nTWqiwzvsziDTAPdk4wDQYJKoZIhvcNAQELBQAw
gY8xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE3MDUGA1UE
AxMuU2VjdGlnbyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
QTAeFw0yMDA0MjgwMDAwMDBaFw0yMTA0MjgyMzU5NTlaMBcxFTATBgNVBAMTDHNz
bDAub3ZoLm5ldDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOmVmvbx
5Wl7HnDdKosd1scDKTX+7osHcSFOMM2zPlU9NDO26SuilV0avXQjzHPKlK99GY3t
47CFaLTlvWeNXJDnYcN+KoPznM3OFdiPfLufeOYpKrLO+RJi1WDfvrLaQgctKJSw
+SipYB0HblWQaH6eJQjVp67LJA6NGqGOLxrHJEAL1a5DnzRKd8WFaXusf+5iwtEu
uSsLAflCx8kel8F0nWKI+knj1nYalb98vrUdsrcGLUkeF990ZwETrx6RI4/GWwpq
kuSn3tmxtyWXhTQgkiNh6hDz3+AVQTp1v42rxynRNgzANRc1XX37qYV8fbVEbnfj
/BGTLrMylf130QKvCXhh2xkp99KGJpHSesodkzFthl19LuTm3mp2CDdF227+QTsZ
YY0ZDPOxrpvGNPskXgfQupGMCqaxB215SbbORKNhht8fT4wcR25Z+bfpvvwlGHCh
PccIOXqaHLjHc8/dv2G8t66XPFkpmf+LGzpvR4P0RT6i6G3NUYHBr+4Adxv46nuh
BDJVwWDfcemdbxZ9di5JDfb7cRENJox0vB4roQKR23rbIrgpyCwu9MjfviWanlOr
vUuu9zgNli9YZPEXmXjpL7936tesT7uUuCEhRCCecejYG8TUeojpXUOVMCcnm9tc
ixHBA11A13lochGzdPumTlYl3pOTZm8vc/khAgMBAAGjggKGMIICgjAfBgNVHSME
GDAWgBSNjF7EVK2K4Xfpm/mbBeG4AY1h4TAdBgNVHQ4EFgQU3ms/wnSQLdy8OIWc
6MFBUpw0Z2cwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw
FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEkGA1UdIARCMEAwNAYLKwYBBAGyMQECAgcw
JTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQIB
MIGEBggrBgEFBQcBAQR4MHYwTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jcnQuc2VjdGln
by5jb20vU2VjdGlnb1JTQURvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5j
cnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMCkGA1UdEQQi
MCCCDHNzbDAub3ZoLm5ldIIQd3d3LnNzbDAub3ZoLm5ldDCCAQQGCisGAQQB1nkC
BAIEgfUEgfIA8AB2AH0+8viP/4hVaCTCwMqeUol5K8UOeAl/LmqXaJl+IvDXAAAB
ccEJ9CIAAAQDAEcwRQIhAO/y/kRhgbJNJjoaAvoch5wfTSwPaK2JIvrVaP1SFQmW
AiBeCdRgQqBVxGmNCFrIAP/jN4afQVhOeZJrIcHJmANV7wB2AJQgvB6O1Y1siHMf
gosiLA3R2k1ebE+UPWHbTi9YTaLCAAABccEJ9EgAAAQDAEcwRQIhAOtOEaYg+esw
zZZSL9mm8XKq2v6kRCGA7/ZNPZWE1lc6AiAdj0lzPvyJD0oc3mOHDR4mdlfnLrY9
4x5uc5xknWh9PDANBgkqhkiG9w0BAQsFAAOCAQEATmrjXr1OguegMTm5H1yHcd/2
lGyPL/Hl7uBL069XOgZ3k2t7F25CWBkGsB6dzI7Qpwr9ODlPR1U8c/Y59X5rOjaR
AZraW2jAd96n2Yc6155WvwENQbgCwS0iMn5u1V3z+M1TG4FI7B30dEOFvMsljGIF
j7gn8LH+BxZMB/+ch6qY0huXy3K5A53OX4Ten85UVKuZBiG3yxvzfFX5mlY7PnDf
zcFGxc3SvcnTZS0HYHE+qv7SzpkuvBc4p/TIKu6zuCtNjwZJpSoJ6p/272dFMzav
ToVNMOK0AVYARP8W0mYeWfzIor+sjIwRshNrUbi112PKxhcozm9KW8tbagmw8w==
-----END CERTIFICATE-----
 1 s:C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
   i:C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
-----BEGIN CERTIFICATE-----
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBjzELMAkGA1UEBhMCR0IxGzAZBgNV
BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE
ChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFJTQSBEb21haW4g
VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA1nMz1tc8INAA0hdFuNY+B6I/x0HuMjDJsGz99J/LEpgPLT+N
TQEMgg8Xf2Iu6bhIefsWg06t1zIlk7cHv7lQP6lMw0Aq6Tn/2YHKHxYyQdqAJrkj
eocgHuP/IJo8lURvh3UGkEC0MpMWCRAIIz7S3YcPb11RFGoKacVPAXJpz9OTTG0E
oKMbgn6xmrntxZ7FN3ifmgg0+1YuWMQJDgZkW7w33PGfKGioVrCSo1yfu4iYCBsk
Haswha6vsC6eep3BwEIc4gLw6uBK0u+QDrTBQBbwb4VCSmT3pDCg/r8uoydajotY
uK3DGReEY+1vVv2Dy2A0xHS+5p3b4eTlygxfFQIDAQABo4IBbjCCAWowHwYDVR0j
BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFI2MXsRUrYrhd+mb
+ZsF4bgBjWHhMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAbBgNVHSAEFDASMAYGBFUdIAAw
CAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0
LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2Bggr
BgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNv
bS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDov
L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMr9hvQ5Iw0/H
ukdN+Jx4GQHcEx2Ab/zDcLRSmjEzmldS+zGea6TvVKqJjUAXaPgREHzSyrHxVYbH
7rM2kYb2OVG/Rr8PoLq0935JxCo2F57kaDl6r5ROVm+yezu/Coa9zcV3HAO4OLGi
H19+24rcRki2aArPsrW04jTkZ6k4Zgle0rj8nSg6F0AnwnJOKf0hPHzPE/uWLMUx
RP0T7dWbqWlod3zu4f+k+TY4CFM5ooQ0nBnzvg6s1SQ36yOoeNDT5++SR2RiOSLv
xvcRviKFxmZEJCaOEDKNyJOuB56DPi/Z+fVGjmO+wea03KbNIaiGCpXZLoUmGv38
sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
-----END CERTIFICATE-----
 2 s:C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
   i:C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
-----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
jjxDah2nGN59PRbxYvnKkKj9
-----END CERTIFICATE-----
---
Server certificate
subject=CN = ssl0.ovh.net

issuer=C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA

---
No client certificate CA names sent
Peer signing digest: SHA512
Peer signature type: RSA
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 5698 bytes and written 397 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 94C2704B41535450C2E914E258FCF4261AE3830EBAF68050A459650A70DD6AE6
    Session-ID-ctx:
    Master-Key: 78941A4567E592C77B7767DBBC5046B91A108F7B2C7A1ED057C274F8C896337894BD28715CCF43EB981A9832DB147E15
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - 7d 83 2f ee 41 40 4d f7-7b 99 ea d7 5f 6e 3b 68   }./.A@M.{..._n;h
    0010 - 05 37 73 e7 89 63 2e 0a-ad 25 23 3f 28 d7 3e ed   .7s..c...%#?(.>.
    0020 - e4 e6 d4 33 52 10 24 49-84 93 7f 33 72 ed 50 20   ...3R.$I...3r.P
    0030 - 9b 55 40 21 01 86 99 37-21 78 bc 04 cb 4c 3a c7   .U@!...7!x...L:.
    0040 - ee 7a 29 45 d3 d0 88 a2-5c 4a d4 bc 56 54 71 0a   .z)E....\J..VTq.
    0050 - c4 e6 85 a1 4e 66 2d 46-7e e9 f2 03 63 97 e9 33   ....Nf-F~...c..3
    0060 - 1b a7 2c f2 9d da 93 03-bc d7 6b d2 c8 84 13 15   ..,.......k.....
    0070 - 46 05 d0 54 ce e5 e8 2a-41 7f 9b 15 a1 00 8a da   F..T...*A.......
    0080 - ff 8a ce 11 91 83 59 4a-47 be d5 18 da 47 4d a7   ......YJG....GM.
    0090 - d4 73 7a 5c 39 a1 21 ac-2b 5e 62 f4 47 ba fc e4   .sz\9.!.+^b.G...
    00a0 - e1 06 7d 80 81 53 9e 00-88 c7 13 d2 bc 07 a0 88   ..}..S..........

    Start Time: 1592435499
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: yes
---
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN] Dovecot on host 103 ready

* BAD Error in IMAP command received by server.

* BAD Error in IMAP command received by server.

* BYE Too many invalid IMAP commands.
closed

Na końcu komunikacji możemy zobaczyć jakie funkcjonalności ma ten serwer IMAP i możemy po tym nagłówku poznać jakie metody uwierzytelnienia są dostępne dla tego serwera. Poniżej kilka działajacych przykładów wykorzystania IMAPsync dla pojedynczej skrzynki:

Z serwera OVH na własny serwer

./imapsync --host1 ssl0.ovh.net --port1 993 --user1 test@test.com --password1 haslo123 --host2 mail.etf2l.site --user2 supra@etf2l.site --password2 haslo123 --ssl1 -ssl2

Z serwera GMail na własny serwer

./imapsync --host1 imap.gmail.com --port1 993 --user1 test@gmail.com --password1 haslo123 --host2 mail.etf2l.site --user2 supra@etf2l.site --password2 haslo123 --ssl1 -ssl2

Przy przykładzie z GMailem warto zerknąć na informacje dotyczące odblokowywania możliwości synchronizacji poniżej.

Z serwera Politechniki Śląskiej na własny serwer

./imapsync --host1 poczta.student.polsl.pl --port1 993 --user1 kontostudenckie@student.polsl.pl --password1 haslo123 --host2 mail.etf2l.site --user2 polsl@etf2l.site --password2 haslo --ssl1 -ssl2

Z serwera Onet.pl na serwer GMail

Przed synchronizacją należy włączyć obsługę IMAP dla konta oraz „dostęp do mniej bezpiecznych aplikacji”:

Taki problem da się też rozpoznać po logu:

Host2 capability before authentication: IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH AUTH
Host2 failure: Error login on [imap.gmail.com] with user [test@gmail.com] auth [LOGIN]: 2 NO [ALERT] Your account is not enabled for IMAP use. Please visit your Gmail settings page and enable your account for IMAP access. (Failure)
Exiting with return value 16 (EXIT_AUTHENTICATION_FAILURE)
Disconnecting from host1 imap.poczta.onet.pl user1 test@onet.pl
Log file is LOG_imapsync/2020_07_23_08_39_05_281_test@onet.pl_test@gmail.com.txt ( to change it, use --logfile filepath ; or use --nolog to turn off logging )

Końcowe polecenie jest takie:

./imapsync --host1 imap.poczta.onet.pl --user1 test@onet.pl --password1 "password123" --host2 imap.gmail.com --port2 993 --user2 test@gmail.com --password2 "password123" --ssl1 -ssl2

Przy okazji odpowiedź na pytanie czemu ja zawsze dostaję tak dużo spamu na moją skrzynkę? – otóż dlatego:

W trakcie rejestracji konta aby mieć skrzynkę za darmo, należy zaznaczyć odpowiednią zgodę, lecz ludzie z reguły nie czytają tego i klikają opcję na samej górze. To powoduje, że Onet.pl i ich partnerzy będą za Waszym przyzwoleniem wysyłać do Was spam. Po kliknięciu Załóż konto jednak przekonuje się, że się myliłem:

Ponadto ich oferta cenowa ze skrzynkami dla prywatnych użytkowników to żart w 2020 roku (np. GMail daje to za darmo (nie do końca, bo mogą zbierać dane o użytkownikach, ale funkcjonalnie i bez spamu za darmo)). Inna rzecz, która mnie zaskoczyła to to, że mogłem zarejestrować konto z jednym z najprostszych haseł słownikowych: Zaq12wsx!.

Z serwera WP.pl na serwer GMail

W WP.pl jest ta sama śpiewka, co w Onet.pl z mailami marketingowymi i tym, że da się założyć konto z hasłem Zaq12wsx!, ale przynajmniej Ci zaznaczyli, że te hasło jest kiepskie:

Tutaj podobnie jak w GMail synchronizacja po IMAP jest domyślnie wyłączona, trzeba ją włączyć:

Host2 failure: Error login on [imap.wp.pl] with user [test@wp.pl] auth [LOGIN]: 2 NO Wybrany kanal dostepu nalezy aktywowac w intefejsie WWW
Exiting with return value 16 (EXIT_AUTHENTICATION_FAILURE)
./imapsync --host1 imap.wp.pl --user1 test@wp.pl --password1 "password123" --host2 imap.gmail.com --port2 993 --user2 test@gmail.com --password2 "password123" --ssl1 -ssl2

Z serwera Gazeta.pl na serwer GMail

Tutaj spamik ponownie, ale tym razem da się wyłączyć:

Jednak nie zaznaczyło „powyższej” opcji:

Co ciekawe, wg Gazeta.pl Zaq12wsx! to mocne hasło:

Tutaj jedynie SMTP jest wyłączony (uwaga, gdyby ktoś z tej skrzynki chciał korzystać w Outlooku czy innym kliencie pocztowym). IMAP jest włączony, więc od razu można puścić synchronizację:

./imapsync --host1 imap.gazeta.pl --user1 test@gazeta.pl --password1 "password123" --host2 imap.gmail.com --port2 993 --user2 test@gmail.com --password2 "password123" --ssl1 -ssl2

Z serwera o2.pl na serwer GMail

Interfejs jest identyczny jak ten z WP.pl, te same zgody, te same hasło:

Tak samo jak na WP.pl odpalamy IMAPa:

./imapsync --host1 poczta.o2.pl --user1 test@o2.pl --password1 "password123" --host2 imap.gmail.com --port2 993 --user2 test@gmail.com --password2 "password123" --ssl1 -ssl2

Z własnego serwera na Exchange Online

./imapsync --host1 ssl0.ovh.net --port1 993 --user1 test@test.com --password1 "password123" --host2 outlook.office365.com --user2 test@test.onmicrosoft.com --password2 "password123" --ssl1 -ssl2

Przykład wyniku synchronizacji małej skrzynki:

supra@supra-pc:/mnt/r/supra/Pobrane/imapsync-imapsync-1.945$ ./imapsync --host1 ssl0.ovh.net --port1 993 --user1 test@test.com --password1 "password123" --host2 imap.poczta.onet.pl --user2 test@onet.pl --password2 "password123"
--ssl1 -ssl2
Here is imapsync 1.945 on host supra-pc, a linux system with 16.5/63.9 free GiB of RAM
with Perl 5.26.1 and Mail::IMAPClient 3.42
Transfer started at Thu Jul 23 08:12:33 2020
PID is 38 my PPID is 8
Log file is LOG_imapsync/2020_07_23_08_12_33_744_test@test.com_test@onet.pl.txt ( to change it, use --logfile path ; or use --nolog to turn off logging )
Load is 0.52 0.58 0.59 1/5 on 16 cores
Current directory is /mnt/r/supra/Pobrane/imapsync-imapsync-1.945
Real user id is supra (uid 1000)
Effective user id is supra (euid 1000)
$RCSfile: imapsync,v $ $Revision: 1.945 $ $Date: 2019/06/26 19:30:56 $
Command line used, run by /usr/bin/perl:
./imapsync --host1 ssl0.ovh.net --port1 993 --user1 test@test.com --password1 MASKED --host2 imap.poczta.onet.pl --user2 test@onet.pl --password2 MASKED --ssl1 -ssl2
Temp directory is /tmp ( to change it use --tmpdir dirpath )
kill -QUIT 38 # special behavior: call to sub catch_exit
kill -TERM 38 # special behavior: call to sub catch_exit
kill -INT 38 # special behavior: call to sub catch_reconnect
kill -HUP 38 # special behavior: call to sub catch_print
kill -USR1 38 # special behavior: call to sub toggle_sleep
File /tmp/imapsync.pid does not exist
PID file is /tmp/imapsync.pid ( to change it, use --pidfile filepath ; to avoid it use --pidfile "" )
Writing my PID 38 in /tmp/imapsync.pid
Writing also my logfile name in /tmp/imapsync.pid : LOG_imapsync/2020_07_23_08_12_33_744_test@test.com_test@onet.pl.txt
Modules version list:
Authen::NTLM         1.09
CGI                  4.49
Compress::Zlib       2.074
Crypt::OpenSSL::RSA  0.28
Data::Uniqid         0.12
Digest::HMAC_MD5     1.01
Digest::HMAC_SHA1    1.03
Digest::MD5          2.55
File::Copy::Recursive 0.40
File::Spec           3.67
Getopt::Long         2.49
HTML::Entities       3.69
IO::Socket           1.38
IO::Socket::INET     1.35
IO::Socket::INET6    2.72
IO::Socket::IP       0.38
IO::Socket::SSL      2.060
IO::Tee              0.65
JSON                 4.02
JSON::WebToken       0.10
LWP                  6.31
Mail::IMAPClient     3.42
Net::Ping            2.55
Net::SSLeay          1.84
Term::ReadKey        2.37
Test::MockObject     1.20161202
Time::HiRes          1.9741
URI::Escape          3.31
Unicode::String      2.10
( use --no-modulesversion to turn off printing this Perl modules list )
Info: will resync flags for already transferred messages. Use --noresyncflags to not resync flags.
SSL debug mode level is --debugssl 1 (can be set from 0 meaning no debug to 4 meaning max debug)
Host1: SSL default mode is like --sslargs1 "SSL_verify_mode=0", meaning for host1 SSL_VERIFY_NONE, ie, do not check the certificate server.
Host1: Use --sslargs1 SSL_verify_mode=1 to have SSL_VERIFY_PEER, ie, check the certificate server of host1
Host2: SSL default mode is like --sslargs2 "SSL_verify_mode=0", meaning for host2 SSL_VERIFY_NONE, ie, do not check the certificate server.
Host2: Use --sslargs2 SSL_verify_mode=1 to have SSL_VERIFY_PEER, ie, check the certificate server of host2
Info: turned ON syncinternaldates, will set the internal dates (arrival dates) on host2 same as host1.
Host1: will try to use LOGIN authentication on host1
Host2: will try to use LOGIN authentication on host2
Host1: imap connection timeout is 120 seconds
Host2: imap connection timeout is 120 seconds
Host1: IMAP server [ssl0.ovh.net] port [993] user [test@test.com]
Host2: IMAP server [imap.poczta.onet.pl] port [993] user [test@onet.pl]
Host1: connecting and login on host1 [ssl0.ovh.net] port [993] with user [test@test.com]
Host1 IP address: 193.70.18.144
Host1 banner: * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN] Dovecot on host 103 ready
Host1 capability before authentication: IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN AUTH
Host1: ssl0.ovh.net says it has CAPABILITY for AUTHENTICATE LOGIN
Host1: success login on [ssl0.ovh.net] with user [test@test.com] auth [LOGIN]
Host2: connecting and login on host2 [imap.poczta.onet.pl] port [993] with user [test@onet.pl]
Host2 IP address: 213.180.147.154
Host2 banner: * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID SORT SORT=DISPLAY MULTIAPPEND UNSELECT CHILDREN UIDPLUS LIST-STATUS LIST-EXTENDED I18NLEVEL=1 SEARCHRES WITHIN AUTH=PLAIN AUTH=LOGIN AUTH=XOAUTH2] Onet server ready.
Host2 capability before authentication: IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID SORT SORT=DISPLAY MULTIAPPEND UNSELECT CHILDREN UIDPLUS LIST-STATUS LIST-EXTENDED I18NLEVEL=1 SEARCHRES WITHIN AUTH=PLAIN AUTH=LOGIN AUTH=XOAUTH2 I18NLEVEL AUTH
Host2: imap.poczta.onet.pl says it has CAPABILITY for AUTHENTICATE LOGIN
Host2: success login on [imap.poczta.onet.pl] with user [test@onet.pl] auth [LOGIN]
Host1: state Authenticated
Host2: state Authenticated
Host1 capability once authenticated: IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE QUOTA THREAD I18NLEVEL CONTEXT
Host2 capability once authenticated: IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID SORT SORT=DISPLAY MULTIAPPEND UNSELECT CHILDREN UIDPLUS LIST-STATUS LIST-EXTENDED I18NLEVEL=1 SEARCHRES WITHIN I18NLEVEL

Host1: found ID capability. Sending/receiving ID, presented in raw IMAP for now.
In order to avoid sending/receiving ID, use option --noid
Sending: 4 ID ("name" "imapsync" "version" "1.945" "os" "linux" "vendor" "Gilles LAMIRAL" "support-url" "https://imapsync.lamiral.info/" "date" "26-Jun-2019 19:30:56 +0000" "side" "host1")
Sent 181 bytes
Read:   * ID ("name" "Dovecot")
        4 OK ID completed (0.000 + 0.000 secs).


Host2: found ID capability. Sending/receiving ID, presented in raw IMAP for now.
In order to avoid sending/receiving ID, use option --noid
Sending: 4 ID ("name" "imapsync" "version" "1.945" "os" "linux" "vendor" "Gilles LAMIRAL" "support-url" "https://imapsync.lamiral.info/" "date" "26-Jun-2019 19:30:56 +0000" "side" "host2")
Sent 181 bytes
Read:   * ID ("name" "NIL")
        4 OK ID completed (0.001 + 0.000 secs).

Host1: found 13 folders.
Host2: found 8 folders.
Host1: guessing separator from folder listing: [.]
Host1: separator given by NAMESPACE: [.]
Host2: guessing separator from folder listing: [/]
Host2: No NAMESPACE capability, so using guessed separator [/]
You can set the separator character with the --sep2 option,
the complete listing of folders may help you to find it
[Powiadomienia]
[Oferty]
[Spo&AUI-eczno&AVs-ci]
[Drafts]
[Junk]
[Sent]
[Trash]
[INBOX]
Host1: guessing prefix from folder listing: [INBOX.]
Host1: prefix given by NAMESPACE: [INBOX.]
Host2: guessing prefix from folder listing: []
Host2: No NAMESPACE capability so using guessed prefix []
You can set the prefix namespace with the --prefix2 option,
the folowing listing of folders may help you to find it:
[Powiadomienia]
[Oferty]
[Spo&AUI-eczno&AVs-ci]
[Drafts]
[Junk]
[Sent]
[Trash]
[INBOX]
Host1: separator and prefix: [.][INBOX.]
Host2: separator and prefix: [/][]
Including all folders found by default. Use --subscribed or --folder or --folderrec or --include to select specific folders. Use --exclude to unselect specific folders.
Host1: Checking wanted folders exist. Use --nocheckfoldersexist to avoid this check (shared of public namespace targeted).
Host1: Checking wanted folders are selectable. Use --nocheckselectable to avoid this check.
Turned off automapping folders ( use --automap to turn on automapping )

++++ Listing folders
All foldernames are presented between brackets like [X] where X is the foldername.
When a foldername contains non-ASCII characters it is presented in the form
[X] = [Y] where
X is the imap foldername you have to use in command line options and
Y is the utf8 output just printed for convenience, to recognize it.

Host1: folders list (first the raw imap format then the [X] = [Y]):
* LIST (\HasChildren) "." INBOX
* LIST (\HasNoChildren) "." "INBOX.ESET Antispam"
* LIST (\HasNoChildren) "." INBOX.INBOX.Sent
* LIST (\HasNoChildren) "." INBOX.INBOX.Junk
* LIST (\HasNoChildren) "." INBOX.INBOX.Drafts
* LIST (\HasNoChildren) "." INBOX.INBOX.Trash
* LIST (\HasNoChildren) "." INBOX.Trash
* LIST (\HasNoChildren) "." INBOX.Wiadomo&AVs-ci-&AVs-mieci
* LIST (\HasNoChildren) "." "INBOX.Elementy wys&AUI-ane"
* LIST (\HasNoChildren) "." INBOX.Sent
* LIST (\HasNoChildren) "." "INBOX.Elementy usuni&ARk-te"
* LIST (\HasNoChildren) "." "INBOX.Wersje robocze"
* LIST (\HasNoChildren) "." "INBOX.Wykryte elementy"
22 OK List completed (0.000 + 0.000 secs).

[INBOX]
[INBOX.ESET Antispam]
[INBOX.Elementy usuni&ARk-te] = [INBOX.Elementy usunięte]
[INBOX.Elementy wys&AUI-ane] = [INBOX.Elementy wysłane]
[INBOX.INBOX.Drafts]
[INBOX.INBOX.Junk]
[INBOX.INBOX.Sent]
[INBOX.INBOX.Trash]
[INBOX.Sent]
[INBOX.Trash]
[INBOX.Wersje robocze]
[INBOX.Wiadomo&AVs-ci-&AVs-mieci] = [INBOX.Wiadomości-śmieci]
[INBOX.Wykryte elementy]

Host2: folders list (first the raw imap format then the [X] = [Y]):
* LIST (\NoInferiors) "/" Powiadomienia
* LIST (\NoInferiors) "/" Oferty
* LIST (\NoInferiors) "/" Spo&AUI-eczno&AVs-ci
* LIST (\NoInferiors) "/" Drafts
* LIST (\NoInferiors) "/" Junk
* LIST (\NoInferiors) "/" Sent
* LIST (\NoInferiors) "/" Trash
* LIST (\NoInferiors) "/" INBOX
9 OK List completed (0.001 + 0.000 secs).

[Drafts]
[INBOX]
[Junk]
[Oferty]
[Powiadomienia]
[Sent]
[Spo&AUI-eczno&AVs-ci] = [Społeczności]
[Trash]

Folders in host2 not in host1:
[Spo&AUI-eczno&AVs-ci] = [Społeczności]
[Powiadomienia]
[Oferty]
[Junk]
[Drafts]


Folders sizes before the synchronization.
You can remove foldersizes listings by using "--nofoldersizes" and "--nofoldersizesatend"
but then you will also lose the ETA (Estimation Time of Arrival) given after each message copy.
++++ Calculating sizes of 13 folders on Host1
Host1 folder    1/13 [INBOX]                             Size:     42026 Messages:     8 Biggest:      7928
Host1 folder    2/13 [INBOX.ESET Antispam]               Size:         0 Messages:     0 Biggest:         0
Host1 folder    3/13 [INBOX.Elementy usuni&ARk-te] = [INBOX.Elementy usunięte] Size:         0 Messages:     0 Biggest:         0
Host1 folder    4/13 [INBOX.Elementy wys&AUI-ane] = [INBOX.Elementy wysłane] Size:      3211 Messages:     1 Biggest:      3211
Host1 folder    5/13 [INBOX.INBOX.Drafts]                Size:         0 Messages:     0 Biggest:         0
Host1 folder    6/13 [INBOX.INBOX.Junk]                  Size:         0 Messages:     0 Biggest:         0
Host1 folder    7/13 [INBOX.INBOX.Sent]                  Size:       663 Messages:     1 Biggest:       663
Host1 folder    8/13 [INBOX.INBOX.Trash]                 Size:         0 Messages:     0 Biggest:         0
Host1 folder    9/13 [INBOX.Sent]                        Size:         0 Messages:     0 Biggest:         0
Host1 folder   10/13 [INBOX.Trash]                       Size:      5718 Messages:     1 Biggest:      5718
Host1 folder   11/13 [INBOX.Wersje robocze]              Size:         0 Messages:     0 Biggest:         0
Host1 folder   12/13 [INBOX.Wiadomo&AVs-ci-&AVs-mieci] = [INBOX.Wiadomości-śmieci] Size:         0 Messages:     0 Biggest:         0
Host1 folder   13/13 [INBOX.Wykryte elementy]            Size:         0 Messages:     0 Biggest:         0
Host1 Nb folders:               13 folders
Host1 Nb messages:              11 messages
Host1 Total size:            51618 bytes (50.408 KiB)
Host1 Biggest message:        7928 bytes (7.742 KiB)
Host1 Time spent:              3.7 seconds
++++ Calculating sizes of 13 folders on Host2
Host2 folder    1/13 [ESET Antispam]                     does not exist yet
Host2 folder    2/13 [Elementy usuni&ARk-te] = [Elementy usunięte] does not exist yet
Host2 folder    3/13 [Elementy wys&AUI-ane] = [Elementy wysłane] does not exist yet
Host2 folder    4/13 [INBOX]                             Size:    286065 Messages:     2 Biggest:    231514
Host2 folder    5/13 [INBOX/Drafts]                      does not exist yet
Host2 folder    6/13 [INBOX/Junk]                        does not exist yet
Host2 folder    7/13 [INBOX/Sent]                        does not exist yet
Host2 folder    8/13 [INBOX/Trash]                       does not exist yet
Host2 folder    9/13 [Sent]                              Size:         0 Messages:     0 Biggest:         0
Host2 folder   10/13 [Trash]                             Size:         0 Messages:     0 Biggest:         0
Host2 folder   11/13 [Wersje robocze]                    does not exist yet
Host2 folder   12/13 [Wiadomo&AVs-ci-&AVs-mieci] = [Wiadomości-śmieci] does not exist yet
Host2 folder   13/13 [Wykryte elementy]                  does not exist yet
Host2 Nb folders:               13 folders
Host2 Nb messages:               2 messages
Host2 Total size:           286065 bytes (279.360 KiB)
Host2 Biggest message:      231514 bytes (226.088 KiB)
Host2 Time spent:              0.1 seconds
++++ Looping on each one of 13 folders to sync
Folder    1/13 [INBOX]                             -> [INBOX]
Host1: folder [INBOX] has 8 messages in total (mentioned by SELECT)
Host2: folder [INBOX] has 2 messages in total (mentioned by SELECT)
Host2: folder [INBOX] permanentflags:
Host1: folder [INBOX] considering 8 messages
Host2: folder [INBOX] considering 2 messages
Host1: folder [INBOX] selected 8 messages, duplicates 0
Host2: INBOX/1 size 54569 ignored (no wanted headers so we ignore this message)
Host2: folder [INBOX] selected 2 messages, duplicates 0
msg INBOX/1 {6599}            copied to INBOX/3          1.00 msgs/s  6.444 KiB/s 6.444 KiB copied ETA: Thu Jul 23 08:12:48 2020  10 s  10/11 msgs left
msg INBOX/2 {4128}            copied to INBOX/4          2.00 msgs/s  10.476 KiB/s 10.476 KiB copied ETA: Thu Jul 23 08:12:42 2020  4 s  9/11 msgs left
msg INBOX/4 {4152}            copied to INBOX/5          3.00 msgs/s  14.530 KiB/s 14.530 KiB copied ETA: Thu Jul 23 08:12:41 2020  3 s  8/11 msgs left
msg INBOX/5 {4711}            copied to INBOX/6          3.87 msgs/s  18.503 KiB/s 19.131 KiB copied ETA: Thu Jul 23 08:12:40 2020  2 s  7/11 msgs left
msg INBOX/6 {5690}            copied to INBOX/7          4.22 msgs/s  20.858 KiB/s 24.688 KiB copied ETA: Thu Jul 23 08:12:40 2020  1 s  6/11 msgs left
msg INBOX/7 {3635}            copied to INBOX/8          4.42 msgs/s  20.812 KiB/s 28.237 KiB copied ETA: Thu Jul 23 08:12:40 2020  1 s  5/11 msgs left
msg INBOX/8 {7928}            copied to INBOX/9          4.65 msgs/s  23.916 KiB/s 35.979 KiB copied ETA: Thu Jul 23 08:12:39 2020  1 s  4/11 msgs left
msg INBOX/9 {5183}            copied to INBOX/10         4.81 msgs/s  24.685 KiB/s 41.041 KiB copied ETA: Thu Jul 23 08:12:39 2020  1 s  3/11 msgs left
Folder    2/13 [INBOX.ESET Antispam]               -> [ESET Antispam]
Host1: folder [INBOX.ESET Antispam] has 0 messages in total (mentioned by SELECT)
Creating folder [ESET Antispam] on host2
Created folder [ESET Antispam] on host2
Host2: folder [ESET Antispam] has 0 messages in total (mentioned by SELECT)
Host2: folder [ESET Antispam] permanentflags:
Host2: Subscribing to folder ESET Antispam
Host1: folder [INBOX.ESET Antispam] considering 0 messages
Host2: folder [ESET Antispam] considering 0 messages
Host1: folder [INBOX.ESET Antispam] selected 0 messages, duplicates 0
Host2: folder [ESET Antispam] selected 0 messages, duplicates 0
Folder    3/13 [INBOX.Elementy usuni&ARk-te] = [INBOX.Elementy usunięte] -> [Elementy usuni&ARk-te] = [Elementy usunięte]
Host1: folder [INBOX.Elementy usuni&ARk-te] has 0 messages in total (mentioned by SELECT)
Creating folder [Elementy usuni&ARk-te] on host2
Folder [Elementy usuni&ARk-te] already exists (--nomixfolders is not set)
Host2: folder [Elementy usuni&ARk-te] has 0 messages in total (mentioned by SELECT)
Host2: folder [Elementy usuni&ARk-te] permanentflags:
Host2: Subscribing to folder Elementy usuni&ARk-te
Host1: folder [INBOX.Elementy usuni&ARk-te] considering 0 messages
Host2: folder [Elementy usuni&ARk-te] considering 0 messages
Host1: folder [INBOX.Elementy usuni&ARk-te] selected 0 messages, duplicates 0
Host2: folder [Elementy usuni&ARk-te] selected 0 messages, duplicates 0
Folder    4/13 [INBOX.Elementy wys&AUI-ane] = [INBOX.Elementy wysłane] -> [Elementy wys&AUI-ane] = [Elementy wysłane]
Host1: folder [INBOX.Elementy wys&AUI-ane] has 1 messages in total (mentioned by SELECT)
Creating folder [Elementy wys&AUI-ane] on host2
Folder [Elementy wys&AUI-ane] already exists (--nomixfolders is not set)
Host2: folder [Elementy wys&AUI-ane] has 0 messages in total (mentioned by SELECT)
Host2: folder [Elementy wys&AUI-ane] permanentflags:
Host2: Subscribing to folder Elementy wys&AUI-ane
Host1: folder [INBOX.Elementy wys&AUI-ane] considering 1 messages
Host2: folder [Elementy wys&AUI-ane] considering 0 messages
Host1: folder [INBOX.Elementy wys&AUI-ane] selected 1 messages, duplicates 0
Host2: folder [Elementy wys&AUI-ane] selected 0 messages, duplicates 0
msg INBOX.Elementy wys&AUI-ane/1 {3211}            copied to Elementy wys&AUI-ane/1          3.55 msgs/s  17.422 KiB/s 44.177 KiB copied ETA: Thu Jul 23 08:12:40 2020  1 s  2/11 msgs left
Folder    5/13 [INBOX.INBOX.Drafts]                -> [INBOX/Drafts]
Host1: folder [INBOX.INBOX.Drafts] has 0 messages in total (mentioned by SELECT)
Creating folder [INBOX/Drafts] on host2
Created folder [INBOX/Drafts] on host2
Host2 folder INBOX/Drafts: Could not select: 54 NO Mailbox doesn't exist: INBOX/Drafts (0.003 + 0.000 + 0.002 secs).
Creating folder [INBOX/Drafts] on host2
Created folder [INBOX/Drafts] on host2
Host2 folder INBOX/Drafts: Could not select: 58 NO Mailbox doesn't exist: INBOX/Drafts (0.003 + 0.000 + 0.002 secs).
Folder    6/13 [INBOX.INBOX.Junk]                  -> [INBOX/Junk]
Host1: folder [INBOX.INBOX.Junk] has 0 messages in total (mentioned by SELECT)
Creating folder [INBOX/Junk] on host2
Created folder [INBOX/Junk] on host2
Host2 folder INBOX/Junk: Could not select: 62 NO Mailbox doesn't exist: INBOX/Junk (0.003 + 0.000 + 0.002 secs).
Creating folder [INBOX/Junk] on host2
Created folder [INBOX/Junk] on host2
Host2 folder INBOX/Junk: Could not select: 66 NO Mailbox doesn't exist: INBOX/Junk (0.002 + 0.000 + 0.001 secs).
Folder    7/13 [INBOX.INBOX.Sent]                  -> [INBOX/Sent]
Host1: folder [INBOX.INBOX.Sent] has 1 messages in total (mentioned by SELECT)
Creating folder [INBOX/Sent] on host2
Created folder [INBOX/Sent] on host2
Host2 folder INBOX/Sent: Could not select: 70 NO Mailbox doesn't exist: INBOX/Sent (0.002 + 0.000 + 0.001 secs).
Creating folder [INBOX/Sent] on host2
Created folder [INBOX/Sent] on host2
Host2 folder INBOX/Sent: Could not select: 74 NO Mailbox doesn't exist: INBOX/Sent (0.002 + 0.000 + 0.001 secs).
Folder    8/13 [INBOX.INBOX.Trash]                 -> [INBOX/Trash]
Host1: folder [INBOX.INBOX.Trash] has 0 messages in total (mentioned by SELECT)
Creating folder [INBOX/Trash] on host2
Created folder [INBOX/Trash] on host2
Host2 folder INBOX/Trash: Could not select: 78 NO Mailbox doesn't exist: INBOX/Trash (0.002 + 0.000 + 0.001 secs).
Creating folder [INBOX/Trash] on host2
Created folder [INBOX/Trash] on host2
Host2 folder INBOX/Trash: Could not select: 82 NO Mailbox doesn't exist: INBOX/Trash (0.002 + 0.000 + 0.001 secs).
Folder    9/13 [INBOX.Sent]                        -> [Sent]
Host1: folder [INBOX.Sent] has 0 messages in total (mentioned by SELECT)
Host2: folder [Sent] has 1 messages in total (mentioned by SELECT)
Host2: folder [Sent] permanentflags:
Host1: folder [INBOX.Sent] considering 0 messages
Host2: folder [Sent] considering 1 messages
Host1: folder [INBOX.Sent] selected 0 messages, duplicates 0
Host2: folder [Sent] selected 1 messages, duplicates 0
Folder   10/13 [INBOX.Trash]                       -> [Trash]
Host1: folder [INBOX.Trash] has 1 messages in total (mentioned by SELECT)
Host2: folder [Trash] has 0 messages in total (mentioned by SELECT)
Host2: folder [Trash] permanentflags:
Host1: folder [INBOX.Trash] considering 1 messages
Host2: folder [Trash] considering 0 messages
Host1: folder [INBOX.Trash] selected 1 messages, duplicates 0
Host2: folder [Trash] selected 0 messages, duplicates 0
msg INBOX.Trash/1 {5718}            copied to Trash/1          2.53 msgs/s  12.601 KiB/s 49.761 KiB copied ETA: Thu Jul 23 08:12:41 2020  0 s  1/11 msgs left
Folder   11/13 [INBOX.Wersje robocze]              -> [Wersje robocze]
Host1: folder [INBOX.Wersje robocze] has 0 messages in total (mentioned by SELECT)
Creating folder [Wersje robocze] on host2
Created folder [Wersje robocze] on host2
Host2: folder [Wersje robocze] has 0 messages in total (mentioned by SELECT)
Host2: folder [Wersje robocze] permanentflags:
Host2: Subscribing to folder Wersje robocze
Host1: folder [INBOX.Wersje robocze] considering 0 messages
Host2: folder [Wersje robocze] considering 0 messages
Host1: folder [INBOX.Wersje robocze] selected 0 messages, duplicates 0
Host2: folder [Wersje robocze] selected 0 messages, duplicates 0
Folder   12/13 [INBOX.Wiadomo&AVs-ci-&AVs-mieci] = [INBOX.Wiadomości-śmieci] -> [Wiadomo&AVs-ci-&AVs-mieci] = [Wiadomości-śmieci]
Host1: folder [INBOX.Wiadomo&AVs-ci-&AVs-mieci] has 0 messages in total (mentioned by SELECT)
Creating folder [Wiadomo&AVs-ci-&AVs-mieci] on host2
Folder [Wiadomo&AVs-ci-&AVs-mieci] already exists (--nomixfolders is not set)
Host2: folder [Wiadomo&AVs-ci-&AVs-mieci] has 0 messages in total (mentioned by SELECT)
Host2: folder [Wiadomo&AVs-ci-&AVs-mieci] permanentflags:
Host2: Subscribing to folder Wiadomo&AVs-ci-&AVs-mieci
Host1: folder [INBOX.Wiadomo&AVs-ci-&AVs-mieci] considering 0 messages
Host2: folder [Wiadomo&AVs-ci-&AVs-mieci] considering 0 messages
Host1: folder [INBOX.Wiadomo&AVs-ci-&AVs-mieci] selected 0 messages, duplicates 0
Host2: folder [Wiadomo&AVs-ci-&AVs-mieci] selected 0 messages, duplicates 0
Folder   13/13 [INBOX.Wykryte elementy]            -> [Wykryte elementy]
Host1: folder [INBOX.Wykryte elementy] has 0 messages in total (mentioned by SELECT)
Creating folder [Wykryte elementy] on host2
Created folder [Wykryte elementy] on host2
Host2: folder [Wykryte elementy] has 0 messages in total (mentioned by SELECT)
Host2: folder [Wykryte elementy] permanentflags:
Host2: Subscribing to folder Wykryte elementy
Host1: folder [INBOX.Wykryte elementy] considering 0 messages
Host2: folder [Wykryte elementy] considering 0 messages
Host1: folder [INBOX.Wykryte elementy] selected 0 messages, duplicates 0
Host2: folder [Wykryte elementy] selected 0 messages, duplicates 0
++++ End looping on each folder

Folders sizes after the synchronization.
You can remove this foldersizes listing by using  "--nofoldersizesatend"
++++ Calculating sizes of 13 folders on Host1
Host1 folder    1/13 [INBOX]                             Size:     42026 Messages:     8 Biggest:      7928
Host1 folder    2/13 [INBOX.ESET Antispam]               Size:         0 Messages:     0 Biggest:         0
Host1 folder    3/13 [INBOX.Elementy usuni&ARk-te] = [INBOX.Elementy usunięte] Size:         0 Messages:     0 Biggest:         0
Host1 folder    4/13 [INBOX.Elementy wys&AUI-ane] = [INBOX.Elementy wysłane] Size:      3211 Messages:     1 Biggest:      3211
Host1 folder    5/13 [INBOX.INBOX.Drafts]                Size:         0 Messages:     0 Biggest:         0
Host1 folder    6/13 [INBOX.INBOX.Junk]                  Size:         0 Messages:     0 Biggest:         0
Host1 folder    7/13 [INBOX.INBOX.Sent]                  Size:       663 Messages:     1 Biggest:       663
Host1 folder    8/13 [INBOX.INBOX.Trash]                 Size:         0 Messages:     0 Biggest:         0
Host1 folder    9/13 [INBOX.Sent]                        Size:         0 Messages:     0 Biggest:         0
Host1 folder   10/13 [INBOX.Trash]                       Size:      5718 Messages:     1 Biggest:      5718
Host1 folder   11/13 [INBOX.Wersje robocze]              Size:         0 Messages:     0 Biggest:         0
Host1 folder   12/13 [INBOX.Wiadomo&AVs-ci-&AVs-mieci] = [INBOX.Wiadomości-śmieci] Size:         0 Messages:     0 Biggest:         0
Host1 folder   13/13 [INBOX.Wykryte elementy]            Size:         0 Messages:     0 Biggest:         0
Host1 Nb folders:               13 folders
Host1 Nb messages:              11 messages
Host1 Total size:            51618 bytes (50.408 KiB)
Host1 Biggest message:        7928 bytes (7.742 KiB)
Host1 Time spent:              1.5 seconds
++++ Calculating sizes of 13 folders on Host2
Host2 folder    1/13 [ESET Antispam]                     Size:         0 Messages:     0 Biggest:         0
Host2 folder    2/13 [Elementy usuni&ARk-te] = [Elementy usunięte] does not exist yet
Host2 folder    3/13 [Elementy wys&AUI-ane] = [Elementy wysłane] does not exist yet
Host2 folder    4/13 [INBOX]                             Size:    328475 Messages:    10 Biggest:    231514
Host2 folder    5/13 [INBOX/Drafts]                      does not exist yet
Host2 folder    6/13 [INBOX/Junk]                        does not exist yet
Host2 folder    7/13 [INBOX/Sent]                        does not exist yet
Host2 folder    8/13 [INBOX/Trash]                       does not exist yet
Host2 folder    9/13 [Sent]                              Size:      3259 Messages:     1 Biggest:      3259
Host2 folder   10/13 [Trash]                             Size:      5766 Messages:     1 Biggest:      5766
Host2 folder   11/13 [Wersje robocze]                    Size:         0 Messages:     0 Biggest:         0
Host2 folder   12/13 [Wiadomo&AVs-ci-&AVs-mieci] = [Wiadomości-śmieci] does not exist yet
Host2 folder   13/13 [Wykryte elementy]                  Size:         0 Messages:     0 Biggest:         0
Host2 Nb folders:               13 folders
Host2 Nb messages:              12 messages
Host2 Total size:           337500 bytes (329.590 KiB)
Host2 Biggest message:      231514 bytes (226.088 KiB)
Host2 Time spent:              0.2 seconds
++++ Statistics
Transfer started on                     : Thu Jul 23 08:12:33 2020
Transfer ended on                       : Thu Jul 23 08:12:43 2020
Transfer time                           : 10.1 sec
Folders synced                          : 13/13 synced
Messages transferred                    : 10
Messages skipped                        : 0
Messages found duplicate on host1       : 0
Messages found duplicate on host2       : 0
Messages found crossduplicate on host2  : 0
Messages void (noheader) on host1       : 0
Messages void (noheader) on host2       : 1
Messages found in host1 not in host2    : 0 messages
Messages found in host2 not in host1    : 1 messages
Messages deleted on host1               : 0
Messages deleted on host2               : 0
Total bytes transferred                 : 50955 (49.761 KiB)
Total bytes skipped                     : 0 (0.000 KiB)
Message rate                            : 1.0 messages/s
Average bandwidth rate                  : 4.9 KiB/s
Reconnections to host1                  : 0
Reconnections to host2                  : 0
Memory consumption at the end           : 188.4 MiB (started with 170.5 MiB)
Load end is                             : 0.52 0.58 0.59 1/5 on 16 cores
Biggest message                         : 7928 bytes (7.742 KiB)
Memory/biggest message ratio            : 24916.5
Start difference host2 - host1          : -9 messages, 234447 bytes (228.952 KiB)
Final difference host2 - host1          : 1 messages, 285882 bytes (279.182 KiB)
The sync looks good, all 10 identified messages in host1 are on host2.
The sync is not strict, there are 1 messages in host2 that are not on host1. Use --delete2 to delete them and have a strict sync.
Detected 8 errors

Check if a new imapsync release is available by adding --releasecheck
Homepage: https://imapsync.lamiral.info/
++++ Listing 8 errors encountered during the sync ( avoid this listing with --noerrorsdump ).
Err 1/8: Host2 folder INBOX/Drafts: Could not select: 54 NO Mailbox doesn't exist: INBOX/Drafts (0.003 + 0.000 + 0.002 secs).
Err 2/8: Host2 folder INBOX/Drafts: Could not select: 58 NO Mailbox doesn't exist: INBOX/Drafts (0.003 + 0.000 + 0.002 secs).
Err 3/8: Host2 folder INBOX/Junk: Could not select: 62 NO Mailbox doesn't exist: INBOX/Junk (0.003 + 0.000 + 0.002 secs).
Err 4/8: Host2 folder INBOX/Junk: Could not select: 66 NO Mailbox doesn't exist: INBOX/Junk (0.002 + 0.000 + 0.001 secs).
Err 5/8: Host2 folder INBOX/Sent: Could not select: 70 NO Mailbox doesn't exist: INBOX/Sent (0.002 + 0.000 + 0.001 secs).
Err 6/8: Host2 folder INBOX/Sent: Could not select: 74 NO Mailbox doesn't exist: INBOX/Sent (0.002 + 0.000 + 0.001 secs).
Err 7/8: Host2 folder INBOX/Trash: Could not select: 78 NO Mailbox doesn't exist: INBOX/Trash (0.002 + 0.000 + 0.001 secs).
Err 8/8: Host2 folder INBOX/Trash: Could not select: 82 NO Mailbox doesn't exist: INBOX/Trash (0.002 + 0.000 + 0.001 secs).
Exiting with return value 111 (EXIT_WITH_ERRORS)
Log file is LOG_imapsync/2020_07_23_08_12_33_744_test@test.com_test@onet.pl.txt ( to change it, use --logfile filepath ; or use --nolog to turn off logging )

Nie znalazłem rozwiązania na błędy, które pojawiają się na samym końcu, więc jeśli ktoś zna rozwiązanie – chętnie o tym posłucham.

Exchange i przenoszenie wielu skrzynek na inny serwer

Tutaj sprawa jest nieco skomplikowana: Exchange domyślnie nie obsługuje IMAPa, to znaczy ta funkcja jest wyłączona. Trzeba ją włączyć i skonfigurować dla użytkowników. Jeśli chodzi o synchronizację wielu użytkowników – niczym się nie różni w stosunku tego, co jest powyżej, poza tym, że robimy to dla wielu użytkowników i czytamy loginy i hasła kont źródłowych i docelowych z pliku CSV. Testy robiłem na Exchange 2019 i do niego będę się odnosił. Nazwa serwera mailowego to mail.serba.website. Poza tym, co wspomniałem, konta muszą być wcześniej utworzone na docelowym serwerze, na który przenosimy skrzynki.

Instrukcja włączania IMAPa jest tutaj, ale ja ją skrócę – poniższe usługi trzeba włączyć i zmienić ich tryb na Automatyczny:

Następnie należy ustawić adres FQDN dla serwera IMAP Exchange’a:

C:\Windows\system32>Set-ImapSettings -ExternalConnectionSettings "mail.serba.website:993:SSL","mail.serba.website:143:TLS" -X509CertificateName mail.serba.website
WARNING: Changes to IMAP4 settings will only take effect after all Microsoft Exchange IMAP4 services are restarted on server EXCHANGE.

Po tym należy wykonać restart usługi:

[PS] C:\Windows\system32>Restart-Service MSExchangeIMAP4; Restart-Service MSExchangeIMAP4BE
WARNING: Waiting for service 'Microsoft Exchange IMAP4 (MSExchangeIMAP4)' to start...
WARNING: Waiting for service 'Microsoft Exchange IMAP4 (MSExchangeIMAP4)' to start...
WARNING: Waiting for service 'Microsoft Exchange IMAP4 Backend (MSExchangeIMAP4BE)' to start...
WARNING: Waiting for service 'Microsoft Exchange IMAP4 Backend (MSExchangeIMAP4BE)' to start...
[PS] C:\Windows\system32>Get-Service MSExchangeIMAP4; Get-Service MSExchangeIMAP4BE

Status   Name               DisplayName
------   ----               -----------
Running  MSExchangeIMAP4    Microsoft Exchange IMAP4
Running  MSExchangeIMAP4BE  Microsoft Exchange IMAP4 Backend

Po tym IMAP działa, ale nie można zapomnieć o tym, by ten miał ważny certyfikat SSL lub jeśli ma samopodpisany lub nieważny, należy użyć opcji --sslargs2 SSL_verify_mode=0 zakładając, że Exchange jest serwerem na który przenosimy skrzynki.

Następnie należy przygotować skrypt, który wykona nam synchronizację oraz plik CSV zawierający loginy i hasła. CSV wygląda tak (zapisany jako konta.csv):

konto1@test.com;haslo1;apilecki@website;haslo1
konto2@test.com;haslo2;bpoprawa@website;haslo2
konto3@test.com;haslo3;fkluk@website;haslo3

Skrypt wygląda tak:

{ while IFS=';' read  u1 p1 u2 p2; do
/mnt/c/Users/Administrator.SERBA/Desktop/imapsync/imapsync --host1 ssl0.ovh.net --user1 "$u1" --password1 "$p1" --ssl1 --port1 993 \
                             --host2 exchange.serba.local --user2 "$u2" --password2 "$p2" -ssl2
                         done ; } < konta.csv

Oczywiście należy podmienić ścieżkę do imapsync na właściwą wcześniej, po tym zapisujemy skrypt jako sync.sh i wykonujemy polecenie bash sync.sh. Po tym skrzynki się zsynchronizują.

Kwestie wydajnościowe

Według zaleceń twórcy IMAPsynca są kwestie, które trzeba wziąć pod uwagę pod kątem synchronizacji i myślę, przy masowych synchronizacjach warto wziąć pod uwagę. Jeśli mamy dużo kont do synchronizacji to można podzielić plik CSV na mniejsze i odpalić osobne procesy dla każdego pliku CSV – w ten sposób więcej synchronizacji można wykonać w jednym czasie, lecz nie ma dokładnego określenia ile ich ma być. Pozostaje testować. Poza tym, warto takie synchronizacje robić z poziomu źródłowego serwera pocztowego lub z docelowego serwera pocztowego (jeśli to jest w ogóle możliwe). To zapewni nam najlepszą wydajność, na przykład jeśli wysyłamy skrzynkę do Office 365 z lokalnego Exchange, warto taki program odpalić bezpośrednio na Exchange’u (jeśli to w ogóle możliwe),

VMware vCenter 7.0 jako podrzędny urząd certyfikacji

Przeczytasz to w: 15 minut

Chcąc dobrze wdrażać środowisko serwerowe zawsze staram się dbać o to, by serwisy webowe w sieci lokalnej posiadały wdrożone certyfikaty SSL, które będą się wyświetlały jako zaufane i ze względu na realia środowisk w Polsce wdrażam urząd certyfikacji na Windowsie (Usługi certyfikatów Active Directory). W przypadku środowiska vSphere jeśli używa się hostów ESXi niezależnie (np. używając darmowej licencji) generuje się certyfikaty dla każdego hosta z osobna. Ten proces jest dosyć prosty i nie będę go tutaj opisywać (może kiedyś indziej opiszę). W przypadku, gdy ma się jednak płatną licencję (jakąkolwiek, Essentials wystarczy) mając vCenter i hosty ESXi podpięte do niego vCenter pełni rolę urzędu certyfikacji, który generuje certyfikaty dla swoich hostów ESXi. Aby taki urząd był zaufany w naszej organizacji opcje są dwie:

  • import domyślnie wygenerowanego certyfikatu vCenter do wszystkich komputerów obsługujących potencjalnie vCenter (najczęściej wszystkie komputery w domenie AD) – kiepskie rozwiązanie ze względu na to, że ta nazwa CA jest po prostu CA, kiepsko to wygląda. Plus jest taki, że po prostu działa bez większych kombinacji.
  • wykorzystanie AD CS i utworzenie certyfikatu podrzędnego urzędu certyfikacji dla vCenter, dzięki czemu nie trzeba nic dodatkowo importować do magazynu zaufanych urzędów certyfikacji we wszystkich komputerach, a z automatu zarówno vCenter jak i hosty ESXi są zaufane, bo po podmianie certyfikatu CA vCenter te pozwoli na wygenerowanie dla swoich podrzędnych podmiotów (hostów ESXi certyfikaty i je wdroży automatycznie) nowych ceryfikatów.

Z faktu, że ja leniwy nie jestem (albo jestem, ale raczej w ten pozytywny sposób 😉) wolę iść tą drugą ścieżką, więc postaram się pokazać w jaki sposób przeprowadzić cały proces krok po kroku. Początkowo męczyłem się z tym całym procesem kilka dni, bo nie umiałem znaleźć dobrego poradnika, który przedstawiał go krok po kroku w prosty sposób, dzięki czemu byłbym w stanie to zrozumieć, lecz znalazłem ten poradnik do starszej wersji vCenter i szczerze polecam go, bo sporo się z niego nauczyłem. W dużej mierze ten poradnik bazuje na wspomnianym. Różnice między tym poradnikiem, który właśnie wspominam, a tym, który właśnie czytacie są takie, że mój jest po polsku, dotyczy vCenter 7.0, który ma tworzenie CSR poprzez GUI, a nie poprzez SSH i dotyczy scenariusza z pojedynczym urzędem certyfikacji (najczęściej w mniejszych firmach wdraża się tylko główny urząd certyfikacji (pośrednie można spotkać w większych firmach). Scenariusz, który tam był przedstawiony zakłada możliwie najbardziej rozbudowany scenariusz, kiedy jest root CA, enterprise CA, policy CA i dopiero nasze vCenter CA. Twórca też wspomina o tym, że mając same Root CA całość się robi bardzo podobnie, ale pamiętam jak bardzo się irytowałem, że tego nie rozumiem, wiec tak czy siak postaram się to pokazać.

Na początku należy się z poziomu konsoli vCenter i włączyć dostęp poprzez SSH do maszyny (jeśli nie jest już włączony), więc klikamy F2 i wpisujemy poświadczenia konta root.

Następnie należy przejść do Troubleshooting Mode Options.

Następnie należy włączyć SSH poprzez Enable SSH. Po tym można wyjść z konfiguracji w konsoli.

Następnie łączymy się poprzez SSH do naszego serwera vCenter:

Obrazek posiada pusty atrybut alt; plik o nazwie image-98.png

Wykonujemy 1 polecenie:

shell.set --enable true

Po tym wykonujemy polecenie shell i dostajemy się do shella bashowego. Tworzymy folder na pliki, które będziemy potrzebowali przenieść, a następnie otwieramy Certificate Managera:

mkdir /tmp/certs
/usr/lib/vmware-vmca/bin/certificate-manager

Pojawi się lista opcji, wybieramy opcję 2. Replace VMCA Root certificate with Custom Signing Certificate and replace all Certificates:

root@vcenter [ ~ ]# /usr/lib/vmware-vmca/bin/certificate-manager
                 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
                |                                                                     |
                |      *** Welcome to the vSphere 6.8 Certificate Manager  ***        |
                |                                                                     |
                |                   -- Select Operation --                            |
                |                                                                     |
                |      1. Replace Machine SSL certificate with Custom Certificate     |
                |                                                                     |
                |      2. Replace VMCA Root certificate with Custom Signing           |
                |         Certificate and replace all Certificates                    |
                |                                                                     |
                |      3. Replace Machine SSL certificate with VMCA Certificate       |
                |                                                                     |
                |      4. Regenerate a new VMCA Root Certificate and                  |
                |         replace all certificates                                    |
                |                                                                     |
                |      5. Replace Solution user certificates with                     |
                |         Custom Certificate                                          |
                |         NOTE: Solution user certs will be deprecated in a future    |
                |         release of vCenter. Refer to release notes for more details.|
                |                                                                     |
                |      6. Replace Solution user certificates with VMCA certificates   |
                |                                                                     |
                |      7. Revert last performed operation by re-publishing old        |
                |         certificates                                                |
                |                                                                     |
                |      8. Reset all Certificates                                      |
                |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
Note : Use Ctrl-D to exit.
Option[1 to 8]: 2

Następnie zostajemy zapytani, czy chcemy wygenerować wszystkie certyfikaty z użyciem pliku konfiguracyjnego, wybieramy Y (tak) i autoryzujemy się poświadczeniami kontem administratora w naszej domenie SSO (domyślnie administrator@vsphere.local):

Please provide valid SSO and VC privileged user credential to perform certificate operations.
Enter username [Administrator@vsphere.local]:administrator@vsphere.local
Enter password:

Po tym jesteśmy proszeni o wypełnienie pól certyfikatu, zdefiniowałem je w następujący sposób:

Please configure certool.cfg with proper values before proceeding to next step.

Press Enter key to skip optional parameters or use Default value.

Enter proper value for 'Country' [Default value : US] : PL

Enter proper value for 'Name' [Default value : CA] : vcenter.serba.local

Enter proper value for 'Organization' [Default value : VMware] : it.supra.tf

Enter proper value for 'OrgUnit' [Default value : VMware Engineering] : IT

Enter proper value for 'State' [Default value : California] : SL

Enter proper value for 'Locality' [Default value : Palo Alto] : Tychy

Enter proper value for 'IPAddress' (Provide comma separated values for multiple IP addresses) [optional] :

Enter proper value for 'Email' [Default value : email@acme.com] : radoslaw@serba.ovh

Enter proper value for 'Hostname' (Provide comma separated values for multiple Hostname entries) [Enter valid Fully Qualified Domain Name(FQDN), For Example : example.domain.com] : vcenter.serba.local

Enter proper value for VMCA 'Name' :vcenter.serba.local

Następnie jesteśmy pytani, czy chcemy zaimportować istniejący certyfikat, czy jedynie wygenerować żądanie podpisania certyfikatu (CSR). Wybieramy opcję 1. Generate Certificate Signing Request(s) and Key(s) for VMCA Root Signing certificate:

     1. Generate Certificate Signing Request(s) and Key(s) for VMCA Root Signing certificate

     2. Import custom certificate(s) and key(s) to replace existing VMCA Root Signing certificate
Option [1 or 2]: 1

Jeśli dostaliśmy następujący wynik, nie ma czym się martwić:

Please provide a directory location to write the CSR(s) and PrivateKey(s) to:
Output directory path: /tmp/certs
2020-07-12T15:47:35.454Z  Running command: ['/usr/lib/vmware-vmca/bin/certool', '--genkey', '--privkey', '/tmp/certs/vmca_issued_key.key', '--pubkey', '/tmp/pubkey.pub']
2020-07-12T15:47:35.536Z  Done running command
2020-07-12T15:47:35.538Z  Running command: ['/usr/lib/vmware-vmca/bin/certool', '--gencacsr', '--privkey', '/tmp/certs/vmca_issued_key.key', '--pubkey', '/tmp/pubkey.pub', '--config', '/var/tmp/vmware/certool.cfg', '--csrfile', '/tmp/certs/vmca_issued_csr.csr']
2020-07-12T15:47:35.775Z  Done running command

W innym wypadku możemy dostać coś takiego:

2020-07-12T15:43:37.467Z INFO certificate-manager Running command: ['/usr/lib/vmware-vmca/bin/certool', '--genkey', '--privkey', '/tmp/certs/vmca_issued_key.key', '--pubkey', '/tmp/pubkey.pub']
2020-07-12T15:43:37.590Z INFO certificate-manager Running command: ['/usr/lib/vmware-vmca/bin/certool', '--gencacsr', '--privkey', '/tmp/certs/vmca_issued_key.key', '--pubkey', '/tmp/pubkey.pub', '--config', '/var/tmp/vmware/certool.cfg', '--csrfile', '/tmp/certs/vmca_issued_csr.csr']
2020-07-12T15:43:37.716Z ERROR certificate-manager Error while generating CSR
2020-07-12T15:43:37.716Z ERROR certificate-manager {
    "detail": [
        {
            "id": "install.ciscommon.command.errinvoke",
            "translatable": "An error occurred while invoking external command : '%(0)s'",
            "args": [
                "Command: ['/usr/lib/vmware-vmca/bin/certool', '--gencacsr', '--privkey', '/tmp/certs/vmca_issued_key.key', '--pubkey', '/tmp/pubkey.pub', '--config', '/var/tmp/vmware/certool.cfg', '--csrfile', '/tmp/certs/vmca_issued_csr.csr']\nStderr: "
            ],
            "localized": "An error occurred while invoking external command : 'Command: ['/usr/lib/vmware-vmca/bin/certool', '--gencacsr', '--privkey', '/tmp/certs/vmca_issued_key.key', '--pubkey', '/tmp/pubkey.pub', '--config', '/var/tmp/vmware/certool.cfg', '--csrfile', '/tmp/certs/vmca_issued_csr.csr']\nStderr: '"
        },
        "Error in generating CSR"
    ],
    "componentKey": null,
    "problemId": null,
    "resolution": null
}
2020-07-12T15:43:37.716Z ERROR certificate-manager Please see log file at /var/log/vmware/vmcad/certificate-manager.log for more information

Moim błędem było to, że w regionie wpisałem śląskie.

Po udanej próbie mamy coś takiego:

     1. Continue to importing Custom certificate(s) and key(s) for VMCA Root Signing certificate

     2. Exit certificate-manager
Option [1 or 2]: 1

Do tego wyboru wrócimy po podpisaniu certyfikatu.

Tak czy siak, do folderu /tmp/certs zostały dodane dwa pliki: vmca_issued_csr.csr oraz vmca_issued_key.key. Musimy te pliki wyciągnąć z vCenter, lecz vCenter 7.0 nie pozwala na włączenie basha jako domyślnego shella, więc posłużymy się innym serwerem z Linuksem i poleceniem scp:

root@vcenter [ /tmp/certs ]# scp * supra@192.168.30.44:/home/supra/certs
The authenticity of host '192.168.30.44 (192.168.30.44)' can't be established.
ECDSA key fingerprint is SHA256:kNv0X0cEkedHTTxYHDjzWCPVus2OW5Pp1WZ9l3NE8qM.
Are you sure you want to continue connecting (yes/no)? yes
supra@192.168.30.44's password:
vmca_issued_csr.csr                           100% 1195   175.5KB/s   00:00
vmca_issued_key.key                           100% 1703     1.7MB/s   00:00

Na dobrą sprawę wystarczy nam sam plik CSR, ale na wszelki wypadek skopiowaliśmy oba. W ten sposób możemy z poziomu Windowsa takie pliki skopiować choćby przez WinSCP:

Następnie należy się zalogować do usługi Web z AD CS służącej do podpisywania certyfikatów wybierając Żądanie certyfikatu:

Następnie wybieramy zaawansowane żądanie certyfikatu.

Następnie w żądaniu trzeba wkleić zawartość pliku vmca_issued_csr.csr, jak powyżej przedstawiony oraz wybrać Szablon certyfikatu o nazwie Podrzędny urząd certyfikacji, a po tym wybrać Prześlij >.

Na końcu pobieramy certyfikat w formacje Base-64.

Na końcu też należy pobrać certyfikat urzędu (lub urzędów certyfikacji) i należy utworzyć plik składający się z zawartości certyfikatu serwera oraz głównego urzędu (w odpowiedniej kolejności). Na głównej stronie urzędu certyfikacji można kliknąć Pobierz certyfikat urzędu certyfikacji, łańcuch certyfikatów lub listę CRL.

Następnie pobieramy certyfikat głównego urzędu certyfikacji wybierając Pobierz certyfikat urzędu certyfikacji mając wcześniej zaznaczony format Base 64.

W moim przypadku ciało certyfikatu serwera to:

-----BEGIN CERTIFICATE-----
MIIGpzCCBI+gAwIBAgITLgAAACmSpTQ5IRDUEwAAAAAAKTANBgkqhkiG9w0BAQsF
ADBFMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFTATBgoJkiaJk/IsZAEZFgVzZXJi
YTEVMBMGA1UEAxMMc2VyYmEtREMxLUNBMB4XDTIwMDcxMjE1NTUwMFoXDTIyMDcx
MjE2MDUwMFowazELMAkGA1UEBhMCUEwxCzAJBgNVBAgTAlNMMQ4wDAYDVQQHEwVU
eWNoeTEUMBIGA1UEChMLaXQuc3VwcmEudGYxCzAJBgNVBAsTAklUMRwwGgYDVQQD
ExN2Y2VudGVyLnNlcmJhLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyHLNgqLJ7c+/6G657tO/pbdkxsUPvGvIAbCLEY7j7Ug6/0c6mC1rQ8R2
me4upGwhmKrl8moh4BAn5QhQUSM3KJQaTgo+a7vDpUFrs4cHMIPfApGR5tuKLv5B
4Sbr6zW/bZq8pxqpt/tosopXjF1nb3IulrTv6nFMq6sjKXYHTY3Gd3yxgky+tRa3
kFdvbyiMnF0NtJ5RMgfDo07O2ob0JWW/wg/mDeUOX3ofsYh9BQ7jOmGoiOtayA08
pGaIdvaI/15zw8MX7MtBxR1p3Ar0JYdzse/91ODDeUH3CCkt3hJdz+r1JBJS39v+
iuUD4Epx2CDaV8GGewAYTMosUlxZAQIDAQABo4ICaDCCAmQwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFOLU6p14frk9ZYIzebfcuJhF
jwTLMDIGA1UdEQQrMCmBEnJhZG9zbGF3QHNlcmJhLm92aIITdmNlbnRlci5zZXJi
YS5sb2NhbDAfBgNVHSMEGDAWgBS7l5n/TyANX99lWhur0laIl0Ox1DCBxgYDVR0f
BIG+MIG7MIG4oIG1oIGyhoGvbGRhcDovLy9DTj1zZXJiYS1EQzEtQ0EsQ049ZGMx
LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD
Tj1Db25maWd1cmF0aW9uLERDPXNlcmJhLERDPWxvY2FsP2NlcnRpZmljYXRlUmV2
b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2lu
dDCB6AYIKwYBBQUHAQEEgdswgdgwgasGCCsGAQUFBzAChoGebGRhcDovLy9DTj1z
ZXJiYS1EQzEtQ0EsQ049QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENO
PVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9c2VyYmEsREM9bG9jYWw/Y0FD
ZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3Jp
dHkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vZGMxLnNlcmJhLmxvY2FsL29jc3AwGQYJ
KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDQYJKoZIhvcNAQELBQADggIBAIiXoJzn
zgWfaRYu0Syv+dtXgx0HBEbfhGTGaC/cOdU1fH0xnimxf0W0LRskeYuJ+NinbigW
hz1Ld1wmdw4Q00qirE5WGeKqy34bV16HW4UY5WA4JUCWwMxjZdLz5+ecdfXxlBPt
eGt+exJrBMRpiviBhYgEEs+XG7S3BSDRRnUWDXqn1bU0r27OicTt2hUZjNo7qoip
M3s0/xzrI73Bim01VZckFcXp1aR9HZpENZnjxcbNQUtoJ8Tww5sbf9vbotRWpQST
HzqGglofK6v7oV2Vc3AA6aU8dwR4a3eAEgEPO3bjLM0J3iAelWVy91aItt+qK60N
gy7fDIU9xQtDcBB6tJrIQPj4vpPC+5p3aXBxE3RjVELNlcVtGqPZG0dXHPYwiOW/
6+822zkIpAnxnYK9qjEpQ0elq+gZZrS4SemWXoYHqn1pPxat7kFwPo6iOLd8GqbR
/UFLuK+uOfbTYZuUCjQgMdJGJhLKosvyE0ypOOsyAQubdd8CM8cQ8PGykl7DI65B
9yupU7ZL8mezjmFvBXEQ6NpyQDTlp/tLz5M1RvyvLVEl96kt/icIK/Yhbi05Vgbc
Hhp6T8l27qZIIaq1tfHSf03IXwbCKVj8zwl2NIbgpFBA8qswjhzEr2vIIUiWxZDQ
m5ao8O7bT+SX3vHSwgwXHprtI8omTkK7RhPI
-----END CERTIFICATE-----

W moim przypadku mam tylko główny urząd certyfikacji i jego certyfikat wygląda tak:

-----BEGIN CERTIFICATE-----
MIIFZTCCA02gAwIBAgIQQu3KocuJColFzyhGGkfTKDANBgkqhkiG9w0BAQsFADBF
MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFTATBgoJkiaJk/IsZAEZFgVzZXJiYTEV
MBMGA1UEAxMMc2VyYmEtREMxLUNBMB4XDTIwMDQwNzE2MzEwOFoXDTMwMDQwNzE2
NDEwOFowRTEVMBMGCgmSJomT8ixkARkWBWxvY2FsMRUwEwYKCZImiZPyLGQBGRYF
c2VyYmExFTATBgNVBAMTDHNlcmJhLURDMS1DQTCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAMuL7eKSxvGBMBES4rA/Ewj0+y+HGi/S/mPoeNWHVMCkigEP
kflji+CdFf5uzQb1iGixeUrCoLcG/YGVR9BYNFadT0lwXsL8pWuGjr0mleR8PjeT
/ybTtqP5DXgUTcP6gKpTv7bwhi3YdFku19Thglt839IP7CUtqP7xdICpxNK+Cj+e
c0qOskBk7TYM2T7BGU6AsXZrpdFTT9LT1jwUA1x1MmIMGB2LFNEQoG+NokT6jxf2
GdJ5yzpwXlD+9QyOljO/y8vyiHJW/soLVXsbylZntNI104Gc9i/kPoWgCrjnWzQs
48p+3c5eO9bU3cTedUKYgiaW8tmy6cCaVc+MM6TRm6ngWmWVhJRd6PpYb8HVpZht
S8hLW7Fq2peiZDscdNy6xfzOast+deRqskl6i0OCc9UFp+vCyuSBQ0aAI4VyMDAM
gYIFWltd8SF/4bSbz4piEwTC1/uyVnVBjzoax0+N8QlaRFv7DU+/F1vd+CQRqdbj
SkQdx0WyDnWPgTqkvO0aRfYtSaVbMFik5CgBmjkqBQsvheRR8RcVoQqZdUwO5S8b
RxGYeWW7uxeJgdDAtO4Vq6ICzmNtF+K8e+qBblcsjdTg1Nza6hx1gJi++Au5+wcp
X5TmgO8TDdNI2sSmMslc+FMOmP4oYjCp8KReDour1NRl0ghIQKvCUgtoMGexAgMB
AAGjUTBPMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS7
l5n/TyANX99lWhur0laIl0Ox1DAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0B
AQsFAAOCAgEAPe01RwAifNPSerFoNLuESB5BR6gO+oXzDqxIzlymTb8FT98aoqF4
s1o6rSZIqwfQtm+scVW7auBEyZm6MXFQHF1UsS4Af7Sqt4X6pc0EHZzt3HEzqy2y
KdO2McLTGe7RCMRt+NmhqiaMUDSbfDn4NO/NXQaYo5ZosrfftIUulrHBlHjr5SI4
62bvaIw+LFUWs9AF6vUkXqV3NKPbNyTbedQ0UQWZSWGtKTgFDxOQSXjlfi113Mx+
gIvXkHj+YBrSA5XZVGGNG727Y1TZzZYa8VZYoqINhnuQ5GYfTXQGWbQRE2uSiCaX
P1e1a9Qjn4atTqetdHd6FiEXfXzSZhoxO2+A8HYlgy0q+bpj7rVS1frwk8xWhnIB
r8op+cQN0hKaNYcrk9joAQUxFUxTLA9Ktj+vA/GX+46s3kmBYelatKMt4S7IlN7e
uOS03dGa0E5Cyyg3AG8Fr2dppEHs6gH5gTt78rs2rDX/WPlhtyqg66XFtPG2g4b1
pJ6iAz/OrgaXiGDArYfsShRshj294bJ6PZiByYZhPvvoEXE7DRNebRwp1ori7g/z
OXMMcIa2+hoNS8XWj6geuVO2V9jfuo12ExzgqGtvklUx8AFMoS41q6yRyFUYbMD/
xZxbaOLbKZJQVWq7fy9bhxc6Ns0lC4jKEf++2Xvpu0tsW1X/BoWywMo=
-----END CERTIFICATE-----

W pliku wysyłanym do vCenter musimy posiadać plik łańcucha składający się z certyfikatu i wszystkich powyższych podmiotów, dzięki którym certyfikat jest zaufany, więc w naszym przypadku w pliku muszą być w kolejności umieszczone zawartość certyfikatu serwera oraz głównego CA. To powinno wyglądać tak:

-----BEGIN CERTIFICATE-----
MIIGpzCCBI+gAwIBAgITLgAAACmSpTQ5IRDUEwAAAAAAKTANBgkqhkiG9w0BAQsF
ADBFMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFTATBgoJkiaJk/IsZAEZFgVzZXJi
YTEVMBMGA1UEAxMMc2VyYmEtREMxLUNBMB4XDTIwMDcxMjE1NTUwMFoXDTIyMDcx
MjE2MDUwMFowazELMAkGA1UEBhMCUEwxCzAJBgNVBAgTAlNMMQ4wDAYDVQQHEwVU
eWNoeTEUMBIGA1UEChMLaXQuc3VwcmEudGYxCzAJBgNVBAsTAklUMRwwGgYDVQQD
ExN2Y2VudGVyLnNlcmJhLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyHLNgqLJ7c+/6G657tO/pbdkxsUPvGvIAbCLEY7j7Ug6/0c6mC1rQ8R2
me4upGwhmKrl8moh4BAn5QhQUSM3KJQaTgo+a7vDpUFrs4cHMIPfApGR5tuKLv5B
4Sbr6zW/bZq8pxqpt/tosopXjF1nb3IulrTv6nFMq6sjKXYHTY3Gd3yxgky+tRa3
kFdvbyiMnF0NtJ5RMgfDo07O2ob0JWW/wg/mDeUOX3ofsYh9BQ7jOmGoiOtayA08
pGaIdvaI/15zw8MX7MtBxR1p3Ar0JYdzse/91ODDeUH3CCkt3hJdz+r1JBJS39v+
iuUD4Epx2CDaV8GGewAYTMosUlxZAQIDAQABo4ICaDCCAmQwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFOLU6p14frk9ZYIzebfcuJhF
jwTLMDIGA1UdEQQrMCmBEnJhZG9zbGF3QHNlcmJhLm92aIITdmNlbnRlci5zZXJi
YS5sb2NhbDAfBgNVHSMEGDAWgBS7l5n/TyANX99lWhur0laIl0Ox1DCBxgYDVR0f
BIG+MIG7MIG4oIG1oIGyhoGvbGRhcDovLy9DTj1zZXJiYS1EQzEtQ0EsQ049ZGMx
LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD
Tj1Db25maWd1cmF0aW9uLERDPXNlcmJhLERDPWxvY2FsP2NlcnRpZmljYXRlUmV2
b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2lu
dDCB6AYIKwYBBQUHAQEEgdswgdgwgasGCCsGAQUFBzAChoGebGRhcDovLy9DTj1z
ZXJiYS1EQzEtQ0EsQ049QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENO
PVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9c2VyYmEsREM9bG9jYWw/Y0FD
ZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3Jp
dHkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vZGMxLnNlcmJhLmxvY2FsL29jc3AwGQYJ
KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDQYJKoZIhvcNAQELBQADggIBAIiXoJzn
zgWfaRYu0Syv+dtXgx0HBEbfhGTGaC/cOdU1fH0xnimxf0W0LRskeYuJ+NinbigW
hz1Ld1wmdw4Q00qirE5WGeKqy34bV16HW4UY5WA4JUCWwMxjZdLz5+ecdfXxlBPt
eGt+exJrBMRpiviBhYgEEs+XG7S3BSDRRnUWDXqn1bU0r27OicTt2hUZjNo7qoip
M3s0/xzrI73Bim01VZckFcXp1aR9HZpENZnjxcbNQUtoJ8Tww5sbf9vbotRWpQST
HzqGglofK6v7oV2Vc3AA6aU8dwR4a3eAEgEPO3bjLM0J3iAelWVy91aItt+qK60N
gy7fDIU9xQtDcBB6tJrIQPj4vpPC+5p3aXBxE3RjVELNlcVtGqPZG0dXHPYwiOW/
6+822zkIpAnxnYK9qjEpQ0elq+gZZrS4SemWXoYHqn1pPxat7kFwPo6iOLd8GqbR
/UFLuK+uOfbTYZuUCjQgMdJGJhLKosvyE0ypOOsyAQubdd8CM8cQ8PGykl7DI65B
9yupU7ZL8mezjmFvBXEQ6NpyQDTlp/tLz5M1RvyvLVEl96kt/icIK/Yhbi05Vgbc
Hhp6T8l27qZIIaq1tfHSf03IXwbCKVj8zwl2NIbgpFBA8qswjhzEr2vIIUiWxZDQ
m5ao8O7bT+SX3vHSwgwXHprtI8omTkK7RhPI
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFZTCCA02gAwIBAgIQQu3KocuJColFzyhGGkfTKDANBgkqhkiG9w0BAQsFADBF
MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFTATBgoJkiaJk/IsZAEZFgVzZXJiYTEV
MBMGA1UEAxMMc2VyYmEtREMxLUNBMB4XDTIwMDQwNzE2MzEwOFoXDTMwMDQwNzE2
NDEwOFowRTEVMBMGCgmSJomT8ixkARkWBWxvY2FsMRUwEwYKCZImiZPyLGQBGRYF
c2VyYmExFTATBgNVBAMTDHNlcmJhLURDMS1DQTCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAMuL7eKSxvGBMBES4rA/Ewj0+y+HGi/S/mPoeNWHVMCkigEP
kflji+CdFf5uzQb1iGixeUrCoLcG/YGVR9BYNFadT0lwXsL8pWuGjr0mleR8PjeT
/ybTtqP5DXgUTcP6gKpTv7bwhi3YdFku19Thglt839IP7CUtqP7xdICpxNK+Cj+e
c0qOskBk7TYM2T7BGU6AsXZrpdFTT9LT1jwUA1x1MmIMGB2LFNEQoG+NokT6jxf2
GdJ5yzpwXlD+9QyOljO/y8vyiHJW/soLVXsbylZntNI104Gc9i/kPoWgCrjnWzQs
48p+3c5eO9bU3cTedUKYgiaW8tmy6cCaVc+MM6TRm6ngWmWVhJRd6PpYb8HVpZht
S8hLW7Fq2peiZDscdNy6xfzOast+deRqskl6i0OCc9UFp+vCyuSBQ0aAI4VyMDAM
gYIFWltd8SF/4bSbz4piEwTC1/uyVnVBjzoax0+N8QlaRFv7DU+/F1vd+CQRqdbj
SkQdx0WyDnWPgTqkvO0aRfYtSaVbMFik5CgBmjkqBQsvheRR8RcVoQqZdUwO5S8b
RxGYeWW7uxeJgdDAtO4Vq6ICzmNtF+K8e+qBblcsjdTg1Nza6hx1gJi++Au5+wcp
X5TmgO8TDdNI2sSmMslc+FMOmP4oYjCp8KReDour1NRl0ghIQKvCUgtoMGexAgMB
AAGjUTBPMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS7
l5n/TyANX99lWhur0laIl0Ox1DAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0B
AQsFAAOCAgEAPe01RwAifNPSerFoNLuESB5BR6gO+oXzDqxIzlymTb8FT98aoqF4
s1o6rSZIqwfQtm+scVW7auBEyZm6MXFQHF1UsS4Af7Sqt4X6pc0EHZzt3HEzqy2y
KdO2McLTGe7RCMRt+NmhqiaMUDSbfDn4NO/NXQaYo5ZosrfftIUulrHBlHjr5SI4
62bvaIw+LFUWs9AF6vUkXqV3NKPbNyTbedQ0UQWZSWGtKTgFDxOQSXjlfi113Mx+
gIvXkHj+YBrSA5XZVGGNG727Y1TZzZYa8VZYoqINhnuQ5GYfTXQGWbQRE2uSiCaX
P1e1a9Qjn4atTqetdHd6FiEXfXzSZhoxO2+A8HYlgy0q+bpj7rVS1frwk8xWhnIB
r8op+cQN0hKaNYcrk9joAQUxFUxTLA9Ktj+vA/GX+46s3kmBYelatKMt4S7IlN7e
uOS03dGa0E5Cyyg3AG8Fr2dppEHs6gH5gTt78rs2rDX/WPlhtyqg66XFtPG2g4b1
pJ6iAz/OrgaXiGDArYfsShRshj294bJ6PZiByYZhPvvoEXE7DRNebRwp1ori7g/z
OXMMcIa2+hoNS8XWj6geuVO2V9jfuo12ExzgqGtvklUx8AFMoS41q6yRyFUYbMD/
xZxbaOLbKZJQVWq7fy9bhxc6Ns0lC4jKEf++2Xvpu0tsW1X/BoWywMo=
-----END CERTIFICATE-----

W przypadku, gdybyśmy mieli jeszcze pośredni urząd certyfikacji między certyfikatem serwera vCenter a głównym urzędem, końcowy plik wyglądałby tak strukturalnie:

  • Certyfikat vCenter
  • Certyfikat pośredniego urzędu certyfikacji
  • Certyfikat głównego urzędu certyfikacji

Czyli mniej więcej tak:

-----BEGIN CERTIFICATE-----
MIIGpzCCBI+gAwIBAgITLgAAACmSpTQ5IRDUEwAAAAAAKTANBgkqhkiG9w0BAQsF
ADBFMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFTATBgoJkiaJk/IsZAEZFgVzZXJi
YTEVMBMGA1UEAxMMc2VyYmEtREMxLUNBMB4XDTIwMDcxMjE1NTUwMFoXDTIyMDcx
MjE2MDUwMFowazELMAkGA1UEBhMCUEwxCzAJBgNVBAgTAlNMMQ4wDAYDVQQHEwVU
eWNoeTEUMBIGA1UEChMLaXQuc3VwcmEudGYxCzAJBgNVBAsTAklUMRwwGgYDVQQD
ExN2Y2VudGVyLnNlcmJhLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyHLNgqLJ7c+/6G657tO/pbdkxsUPvGvIAbCLEY7j7Ug6/0c6mC1rQ8R2
me4upGwhmKrl8moh4BAn5QhQUSM3KJQaTgo+a7vDpUFrs4cHMIPfApGR5tuKLv5B
4Sbr6zW/bZq8pxqpt/tosopXjF1nb3IulrTv6nFMq6sjKXYHTY3Gd3yxgky+tRa3
kFdvbyiMnF0NtJ5RMgfDo07O2ob0JWW/wg/mDeUOX3ofsYh9BQ7jOmGoiOtayA08
pGaIdvaI/15zw8MX7MtBxR1p3Ar0JYdzse/91ODDeUH3CCkt3hJdz+r1JBJS39v+
iuUD4Epx2CDaV8GGewAYTMosUlxZAQIDAQABo4ICaDCCAmQwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFOLU6p14frk9ZYIzebfcuJhF
jwTLMDIGA1UdEQQrMCmBEnJhZG9zbGF3QHNlcmJhLm92aIITdmNlbnRlci5zZXJi
YS5sb2NhbDAfBgNVHSMEGDAWgBS7l5n/TyANX99lWhur0laIl0Ox1DCBxgYDVR0f
BIG+MIG7MIG4oIG1oIGyhoGvbGRhcDovLy9DTj1zZXJiYS1EQzEtQ0EsQ049ZGMx
LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD
Tj1Db25maWd1cmF0aW9uLERDPXNlcmJhLERDPWxvY2FsP2NlcnRpZmljYXRlUmV2
b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2lu
dDCB6AYIKwYBBQUHAQEEgdswgdgwgasGCCsGAQUFBzAChoGebGRhcDovLy9DTj1z
ZXJiYS1EQzEtQ0EsQ049QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENO
PVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9c2VyYmEsREM9bG9jYWw/Y0FD
ZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3Jp
dHkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vZGMxLnNlcmJhLmxvY2FsL29jc3AwGQYJ
KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDQYJKoZIhvcNAQELBQADggIBAIiXoJzn
zgWfaRYu0Syv+dtXgx0HBEbfhGTGaC/cOdU1fH0xnimxf0W0LRskeYuJ+NinbigW
hz1Ld1wmdw4Q00qirE5WGeKqy34bV16HW4UY5WA4JUCWwMxjZdLz5+ecdfXxlBPt
eGt+exJrBMRpiviBhYgEEs+XG7S3BSDRRnUWDXqn1bU0r27OicTt2hUZjNo7qoip
M3s0/xzrI73Bim01VZckFcXp1aR9HZpENZnjxcbNQUtoJ8Tww5sbf9vbotRWpQST
HzqGglofK6v7oV2Vc3AA6aU8dwR4a3eAEgEPO3bjLM0J3iAelWVy91aItt+qK60N
gy7fDIU9xQtDcBB6tJrIQPj4vpPC+5p3aXBxE3RjVELNlcVtGqPZG0dXHPYwiOW/
6+822zkIpAnxnYK9qjEpQ0elq+gZZrS4SemWXoYHqn1pPxat7kFwPo6iOLd8GqbR
/UFLuK+uOfbTYZuUCjQgMdJGJhLKosvyE0ypOOsyAQubdd8CM8cQ8PGykl7DI65B
9yupU7ZL8mezjmFvBXEQ6NpyQDTlp/tLz5M1RvyvLVEl96kt/icIK/Yhbi05Vgbc
Hhp6T8l27qZIIaq1tfHSf03IXwbCKVj8zwl2NIbgpFBA8qswjhzEr2vIIUiWxZDQ
m5ao8O7bT+SX3vHSwgwXHprtI8omTkK7RhPI
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
////////////////////certyfikat pośredniego ca///////////////////
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFZTCCA02gAwIBAgIQQu3KocuJColFzyhGGkfTKDANBgkqhkiG9w0BAQsFADBF
MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFTATBgoJkiaJk/IsZAEZFgVzZXJiYTEV
MBMGA1UEAxMMc2VyYmEtREMxLUNBMB4XDTIwMDQwNzE2MzEwOFoXDTMwMDQwNzE2
NDEwOFowRTEVMBMGCgmSJomT8ixkARkWBWxvY2FsMRUwEwYKCZImiZPyLGQBGRYF
c2VyYmExFTATBgNVBAMTDHNlcmJhLURDMS1DQTCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAMuL7eKSxvGBMBES4rA/Ewj0+y+HGi/S/mPoeNWHVMCkigEP
kflji+CdFf5uzQb1iGixeUrCoLcG/YGVR9BYNFadT0lwXsL8pWuGjr0mleR8PjeT
/ybTtqP5DXgUTcP6gKpTv7bwhi3YdFku19Thglt839IP7CUtqP7xdICpxNK+Cj+e
c0qOskBk7TYM2T7BGU6AsXZrpdFTT9LT1jwUA1x1MmIMGB2LFNEQoG+NokT6jxf2
GdJ5yzpwXlD+9QyOljO/y8vyiHJW/soLVXsbylZntNI104Gc9i/kPoWgCrjnWzQs
48p+3c5eO9bU3cTedUKYgiaW8tmy6cCaVc+MM6TRm6ngWmWVhJRd6PpYb8HVpZht
S8hLW7Fq2peiZDscdNy6xfzOast+deRqskl6i0OCc9UFp+vCyuSBQ0aAI4VyMDAM
gYIFWltd8SF/4bSbz4piEwTC1/uyVnVBjzoax0+N8QlaRFv7DU+/F1vd+CQRqdbj
SkQdx0WyDnWPgTqkvO0aRfYtSaVbMFik5CgBmjkqBQsvheRR8RcVoQqZdUwO5S8b
RxGYeWW7uxeJgdDAtO4Vq6ICzmNtF+K8e+qBblcsjdTg1Nza6hx1gJi++Au5+wcp
X5TmgO8TDdNI2sSmMslc+FMOmP4oYjCp8KReDour1NRl0ghIQKvCUgtoMGexAgMB
AAGjUTBPMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS7
l5n/TyANX99lWhur0laIl0Ox1DAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0B
AQsFAAOCAgEAPe01RwAifNPSerFoNLuESB5BR6gO+oXzDqxIzlymTb8FT98aoqF4
s1o6rSZIqwfQtm+scVW7auBEyZm6MXFQHF1UsS4Af7Sqt4X6pc0EHZzt3HEzqy2y
KdO2McLTGe7RCMRt+NmhqiaMUDSbfDn4NO/NXQaYo5ZosrfftIUulrHBlHjr5SI4
62bvaIw+LFUWs9AF6vUkXqV3NKPbNyTbedQ0UQWZSWGtKTgFDxOQSXjlfi113Mx+
gIvXkHj+YBrSA5XZVGGNG727Y1TZzZYa8VZYoqINhnuQ5GYfTXQGWbQRE2uSiCaX
P1e1a9Qjn4atTqetdHd6FiEXfXzSZhoxO2+A8HYlgy0q+bpj7rVS1frwk8xWhnIB
r8op+cQN0hKaNYcrk9joAQUxFUxTLA9Ktj+vA/GX+46s3kmBYelatKMt4S7IlN7e
uOS03dGa0E5Cyyg3AG8Fr2dppEHs6gH5gTt78rs2rDX/WPlhtyqg66XFtPG2g4b1
pJ6iAz/OrgaXiGDArYfsShRshj294bJ6PZiByYZhPvvoEXE7DRNebRwp1ori7g/z
OXMMcIa2+hoNS8XWj6geuVO2V9jfuo12ExzgqGtvklUx8AFMoS41q6yRyFUYbMD/
xZxbaOLbKZJQVWq7fy9bhxc6Ns0lC4jKEf++2Xvpu0tsW1X/BoWywMo=
-----END CERTIFICATE-----

Nie polecam zostawiać pustej linii na końcu pliku, niekoniecznie przy vCenter, ale przy innym sofcie, który wymagał niestandardowego CA proces stosowania certyfikatu po prostu wysiadał.

Taki plik łańcucha zapisałem w pliku o nazwie vcenter-chain.cer. Następnie umieściłem go na swoim serwerze linuksowym:

Potem dzięki poleceniu SCP skopiowałem plik łańcucha certyfikatu (robiąc to w drugiej, osobnej sesji SSH z vCenter:

root@vcenter [ /tmp/certs ]# scp supra@192.168.30.44:/home/supra/certs/vcenter-chain.cer /tmp/certs/                                  supra@192.168.30.44's password:
vcenter-chain.cer                                                                                   100% 4364     1.1MB/s   00:00

Po tym wracam do sesji, w której tworzyłem klucz prywatny oraz CSR.

 1. Continue to importing Custom certificate(s) and key(s) for VMCA Root Signing certificate

 2. Exit certificate-manager
Option [1 or 2]: 1

Wybieramy opcję 1 i tutaj wybieramy nasz wgrany plik łańcucha certyfikatu oraz plik klucza, który został utworzony przy tworzeniu CSR. Po tym jesteśmy pytani o zatwierdzenie operacji podmiany certyfikatu CA dla vCenter, zatwierdzamy przez Y:

Please provide valid custom certificate for Root.
File : /tmp/certs/vcenter-chain.cer

Please provide valid custom key for Root.
File : /tmp/certs/vmca_issued_key.key

You are going to replace Root Certificate with custom certificate and regenerate all other certificates
Continue operation : Option[Y/N] ? : Y

Następnie musimy poczekać kilka minut, aż import się wykona. Jeśli coś się nie uda na tym etapie (np. źle podamy plik) to zawsze możemy wrócić do tego kreatora ponownie:

root@vcenter [ /tmp/certs ]# /usr/lib/vmware-vmca/bin/certificate-manager
                 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
                |                                                                     |
                |      *** Welcome to the vSphere 6.8 Certificate Manager  ***        |
                |                                                                     |
                |                   -- Select Operation --                            |
                |                                                                     |
                |      1. Replace Machine SSL certificate with Custom Certificate     |
                |                                                                     |
                |      2. Replace VMCA Root certificate with Custom Signing           |
                |         Certificate and replace all Certificates                    |
                |                                                                     |
                |      3. Replace Machine SSL certificate with VMCA Certificate       |
                |                                                                     |
                |      4. Regenerate a new VMCA Root Certificate and                  |
                |         replace all certificates                                    |
                |                                                                     |
                |      5. Replace Solution user certificates with                     |
                |         Custom Certificate                                          |
                |         NOTE: Solution user certs will be deprecated in a future    |
                |         release of vCenter. Refer to release notes for more details.|
                |                                                                     |
                |      6. Replace Solution user certificates with VMCA certificates   |
                |                                                                     |
                |      7. Revert last performed operation by re-publishing old        |
                |         certificates                                                |
                |                                                                     |
                |      8. Reset all Certificates                                      |
                |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
Note : Use Ctrl-D to exit.
Option[1 to 8]: 2
Do you wish to generate all certificates using configuration file : Option[Y/N] ? : n

Please provide valid SSO and VC privileged user credential to perform certificate operations.
Enter username [Administrator@vsphere.local]:administrator@vsphere.local
Enter password:
certool.cfg file exists, Do you wish to reconfigure : Option[Y/N] ? : n
         1. Generate Certificate Signing Request(s) and Key(s) for VMCA Root Signing certificate

         2. Import custom certificate(s) and key(s) to replace existing VMCA Root Signing certificate

Option [1 or 2]: 2

Efekt końcowy powinien być mniej więcej taki:

Get site nameCompleted [Replacing Machine SSL Cert...]
default-site
Lookup all services
Get service default-site:d5d00e27-79af-4c88-b870-5453e9c3d7f9
Update service default-site:d5d00e27-79af-4c88-b870-5453e9c3d7f9; spec: /tmp/svcspec_tyrcm6al
Get service default-site:cdfe4374-ac38-4080-b986-6d6f2a8758b1
Update service default-site:cdfe4374-ac38-4080-b986-6d6f2a8758b1; spec: /tmp/svcspec_79qh8fqn
Get service default-site:31efcc7b-4f50-41b2-ba2e-601fe26e01c8
Update service default-site:31efcc7b-4f50-41b2-ba2e-601fe26e01c8; spec: /tmp/svcspec_ou4iht4l
Get service 9f8fbc47-b4f0-4fba-8335-fb41536e293f
Update service 9f8fbc47-b4f0-4fba-8335-fb41536e293f; spec: /tmp/svcspec_nvteg0if
Get service 669789b0-a7f4-4f4d-96e2-f18dbabd5735
Update service 669789b0-a7f4-4f4d-96e2-f18dbabd5735; spec: /tmp/svcspec_7ocwx_p3
Get service 5e7ac323-d616-45b8-93ce-b2fab8dd28fa
Update service 5e7ac323-d616-45b8-93ce-b2fab8dd28fa; spec: /tmp/svcspec_fx37gzod
Get service 39d31e11-8874-4568-b988-f9e0118d7e9a
Update service 39d31e11-8874-4568-b988-f9e0118d7e9a; spec: /tmp/svcspec_jb7krv5o
Get service 8c1cfd45-49a6-4431-b5db-0c83fec29e11
Update service 8c1cfd45-49a6-4431-b5db-0c83fec29e11; spec: /tmp/svcspec_mqitxjn3
Get service 17f968a2-b2d6-464e-b926-b2d1cd987fcf
Update service 17f968a2-b2d6-464e-b926-b2d1cd987fcf; spec: /tmp/svcspec_sc48jaa0
Get service 26bbde43-6d16-4891-a112-c4265ca742bb
Update service 26bbde43-6d16-4891-a112-c4265ca742bb; spec: /tmp/svcspec_89l9v8eh
Get service 38ad42e1-47e6-4568-9bb8-be32c2f348ed
Update service 38ad42e1-47e6-4568-9bb8-be32c2f348ed; spec: /tmp/svcspec_ztx6d0_0
Get service eae7c217-3b5e-408c-82e3-1ca0cae142a4_com.vmware.vsphere.client
Don't update service eae7c217-3b5e-408c-82e3-1ca0cae142a4_com.vmware.vsphere.client
Get service 9e99b5cc-2d62-4580-8d48-0cecea345256
Update service 9e99b5cc-2d62-4580-8d48-0cecea345256; spec: /tmp/svcspec_q6s7nxup
Get service 721b5dcd-1456-4b24-80c3-7e8a99402f09
Update service 721b5dcd-1456-4b24-80c3-7e8a99402f09; spec: /tmp/svcspec_pbkfqvuq
Get service eae7c217-3b5e-408c-82e3-1ca0cae142a4
Update service eae7c217-3b5e-408c-82e3-1ca0cae142a4; spec: /tmp/svcspec_0gzk00xv
Get service 04eaa9ed-952d-49af-a3f0-22cdcadc095f
Update service 04eaa9ed-952d-49af-a3f0-22cdcadc095f; spec: /tmp/svcspec_s8lnn1j3
Get service ae78a934-21e6-4db5-b072-e605b429b96e
Update service ae78a934-21e6-4db5-b072-e605b429b96e; spec: /tmp/svcspec_7mq2ig_j
Get service 31c27986-27a6-45da-955a-d9ca4d2bf766
Update service 31c27986-27a6-45da-955a-d9ca4d2bf766; spec: /tmp/svcspec_0bl7a7f8
Get service 3305cc60-3e0b-493b-b38e-0852883e29f4
Update service 3305cc60-3e0b-493b-b38e-0852883e29f4; spec: /tmp/svcspec_3i3epoy2
Get service faeae38c-bc5e-4813-b24e-8545b2ac0751
Update service faeae38c-bc5e-4813-b24e-8545b2ac0751; spec: /tmp/svcspec_g0xu28p8
Get service 8cf2be25-2ece-435e-99af-44f205fb323f
Don't update service 8cf2be25-2ece-435e-99af-44f205fb323f
Get service 11fbce0f-217e-4584-a453-8f8ed495bb42
Update service 11fbce0f-217e-4584-a453-8f8ed495bb42; spec: /tmp/svcspec_k7m05w3a
Get service 218c0ecd-6a10-49d1-b18f-78789b35bf8f
Update service 218c0ecd-6a10-49d1-b18f-78789b35bf8f; spec: /tmp/svcspec_wbobnp_s
Get service 5b8e0240-d496-4560-8f72-7a189fd6699f
Update service 5b8e0240-d496-4560-8f72-7a189fd6699f; spec: /tmp/svcspec_lf2ubwfh
Get service 7d6f91e4-f69e-4a8f-83bc-5ed957c74ab5
Don't update service 7d6f91e4-f69e-4a8f-83bc-5ed957c74ab5
Get service 8cd70ec7-23a4-4576-b5d7-223d54ac5a02
Update service 8cd70ec7-23a4-4576-b5d7-223d54ac5a02; spec: /tmp/svcspec_b88uwq07
Get service e10f925b-e725-4b74-99f8-f34bef4ff052
Update service e10f925b-e725-4b74-99f8-f34bef4ff052; spec: /tmp/svcspec_yr1k9_7l
Get service faeae38c-bc5e-4813-b24e-8545b2ac0751_authz
Update service faeae38c-bc5e-4813-b24e-8545b2ac0751_authz; spec: /tmp/svcspec_enzp0qlk
Get service 6fb28804-98d7-4c6a-8a89-922829d5165e
Update service 6fb28804-98d7-4c6a-8a89-922829d5165e; spec: /tmp/svcspec_1l157oyi
Get service 9f728793-62a6-423f-9d70-636e79ea4aa0
Update service 9f728793-62a6-423f-9d70-636e79ea4aa0; spec: /tmp/svcspec_720uy0_n
Get service 10499cb2-0cf8-4cc7-8a3b-0ce43100d036
Update service 10499cb2-0cf8-4cc7-8a3b-0ce43100d036; spec: /tmp/svcspec_4i8z510h
Get service 11a9a085-0b48-450f-b159-5156c9d91f57
Update service 11a9a085-0b48-450f-b159-5156c9d91f57; spec: /tmp/svcspec_feo5j4kh
Get service 10085641-bf52-4b16-81b1-9638d7cd8cdf
Update service 10085641-bf52-4b16-81b1-9638d7cd8cdf; spec: /tmp/svcspec_mae6cors
Get service b6e8e560-39a0-4078-af01-64c46f127f86
Update service b6e8e560-39a0-4078-af01-64c46f127f86; spec: /tmp/svcspec_o4mydtex
Get service 7506a154-0396-4cfa-b287-b077f84a2efd
Update service 7506a154-0396-4cfa-b287-b077f84a2efd; spec: /tmp/svcspec_jrqlyujd
Get service d0ffd26c-885d-4281-a595-e4fd49f1d82f
Update service d0ffd26c-885d-4281-a595-e4fd49f1d82f; spec: /tmp/svcspec_popllmkc
Get service df186d16-72a3-4e2a-9bdf-2c3fe81ac078
Update service df186d16-72a3-4e2a-9bdf-2c3fe81ac078; spec: /tmp/svcspec_je2ffoce
Get service 61c350a6-c4f0-43a0-bb78-4b4edbe2bea1
Update service 61c350a6-c4f0-43a0-bb78-4b4edbe2bea1; spec: /tmp/svcspec__xypiunv
Get service cf53c746-dec6-4221-ad2f-2714e6117ae6
Update service cf53c746-dec6-4221-ad2f-2714e6117ae6; spec: /tmp/svcspec_x264am44
Get service 8bcbc603-1b01-48e3-b067-343d09205920
Update service 8bcbc603-1b01-48e3-b067-343d09205920; spec: /tmp/svcspec_t4zfj9uu
Get service 3dc80e24-b4bd-4dbb-ac70-9d6ba4b846c5
Update service 3dc80e24-b4bd-4dbb-ac70-9d6ba4b846c5; spec: /tmp/svcspec_jpezzb_q
Get service 98e27670-8c8a-4ce3-9eff-e876c17ad479
Update service 98e27670-8c8a-4ce3-9eff-e876c17ad479; spec: /tmp/svcspec_s3fj_h16
Get service faeae38c-bc5e-4813-b24e-8545b2ac0751_kv
Update service faeae38c-bc5e-4813-b24e-8545b2ac0751_kv; spec: /tmp/svcspec_65sl6505
Get service 8a260877-5991-4e8b-b350-a66b27ca889f
Update service 8a260877-5991-4e8b-b350-a66b27ca889f; spec: /tmp/svcspec_vcl3r4qc
Get service eae7c217-3b5e-408c-82e3-1ca0cae142a4_com.vmware.vcenter.wcp
Don't update service eae7c217-3b5e-408c-82e3-1ca0cae142a4_com.vmware.vcenter.wcp
Get service eae7c217-3b5e-408c-82e3-1ca0cae142a4_com.vmware.lcm.client
Don't update service eae7c217-3b5e-408c-82e3-1ca0cae142a4_com.vmware.lcm.client
Updated 41 service(s)
Status : 60% Completed [Replace vpxd-extension Cert...]
2020-07-12T16:36:36.187Z  Updating certificate for "com.vmware.vim.eam" extension
2020-07-12T16:36:36.317Z  Successfully updated certificate for "com.vmware.vim.eam" extension


2020-07-12T16:36:37.668Z  Updating certificate for "com.vmware.rbd" extension
2020-07-12T16:36:37.790Z  Successfully updated certificate for "com.vmware.rbd" extension


2020-07-12T16:36:39.670Z  Updating certificate for "com.vmware.imagebuilder" extension

Status : 100% Completed [All tasks completed successfully]

Jak widać, po odświeżeniu strona vCenter jest zaufana:

Pozostaje nam do zaaktualizowania certyfikat ESXi. Należy na nich odświeżyć CA oraz odnowić certyfikat, więc przechodzimy do widoku Hosts and Clusters, wybieramy nasz host, klikamy prawym i wybieramy Certificates > Refresh CA Certificates. Po tym zatwierdzamy operację i robimy to samo z opcją Renew Certificate.

Po tym certyfikat na ESXi też będzie okej:

Pozostają dwie kwestie – nie będzie tak kolorowo z zieloną kłódką na Firefoxie. Wynika to z tego, że hosty ESXi i vCenter przesyłają swój ciąg certyfikacji, który składa się jedynie z vCenter CA i jego własnego certyfikatu. To oznacza, że nie ma w ciągu certyfikatu głównego urzędu certyfikacji:

Szybka analiza przez OpenSSL potwierdziła to:

C:\Users\supra>openssl s_client -showcerts -connect vhost1.serba.local:443
CONNECTED(00000004)
depth=1 C = PL, ST = SL, L = Tychy, O = it.supra.tf, OU = IT, CN = vcenter.serba.local
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, ST = California, L = Palo Alto, O = VMware, OU = VMware Engineering, CN = vhost1.serba.local, emailAddress = vmca@vmware.com
verify return:1
---
Certificate chain
 0 s:C = US, ST = California, L = Palo Alto, O = VMware, OU = VMware Engineering, CN = vhost1.serba.local, emailAddress = vmca@vmware.com
   i:C = PL, ST = SL, L = Tychy, O = it.supra.tf, OU = IT, CN = vcenter.serba.local
-----BEGIN CERTIFICATE-----
MIIEGTCCAwGgAwIBAgIJAMtSRB4kyvtcMA0GCSqGSIb3DQEBCwUAMGsxCzAJBgNV
BAYTAlBMMQswCQYDVQQIEwJTTDEOMAwGA1UEBxMFVHljaHkxFDASBgNVBAoTC2l0
LnN1cHJhLnRmMQswCQYDVQQLEwJJVDEcMBoGA1UEAxMTdmNlbnRlci5zZXJiYS5s
b2NhbDAeFw0yMDA3MTIxNzAxMjRaFw0yMjA3MTIxNjA1MDBaMIGhMQswCQYDVQQG
EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJUGFsbyBBbHRvMQ8w
DQYDVQQKDAZWTXdhcmUxGzAZBgNVBAsMElZNd2FyZSBFbmdpbmVlcmluZzEbMBkG
A1UEAwwSdmhvc3QxLnNlcmJhLmxvY2FsMR4wHAYJKoZIhvcNAQkBFg92bWNhQHZt
d2FyZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDRtdmFj50
2EIbv6DojtoBk3EDE2ZqdJTFPZuti0S2Olil25kaReqQN1Wem/6sF1q6/YyBldKw
zVxsfmnUblts3+sjv5plttzYTcV70Z0XloLOPzGlKZhAM+XS1kJSpjyK93J8+3aM
wwDqEo7WKp3indVdi7dPRSqc7g77RHJgCoNZ49BIn+q2FlTkjUKACa6s/hlPoyi+
1pxfYlbCOsGd8ioYn6MMs5YW3Aib1kkaaFoiPhkFp02V2REIfgaH/vrf66nTMOoc
fwfC+smZaSeIIaVMez8D6v57KTRqCZOrgYRk8FNjLlOvW96JmHELZy8yVEKCufv8
/HVya0RxMyq/AgMBAAGjgYgwgYUwHQYDVR0RBBYwFIISdmhvc3QxLnNlcmJhLmxv
Y2FsMB8GA1UdIwQYMBaAFOLU6p14frk9ZYIzebfcuJhFjwTLMEMGCCsGAQUFBwEB
BDcwNTAzBggrBgEFBQcwAoYnaHR0cHM6Ly92Y2VudGVyLnNlcmJhLmxvY2FsL2Fm
ZC92ZWNzL2NhMA0GCSqGSIb3DQEBCwUAA4IBAQCmWQEGxPYxgBv5rdmazdq0Lvt4
pAOhcP8sQCiKaIaHED93X/9F7JmyqabNfLLsniqyYnZmo49ZmOlD9KoeIRthe4ot
sFj+NzlbtxyTa46dBp3LyVnrmyECjmCUqLLKrsTS0ype02TfwmNVQw94IaufS5JS
giXToHFPulR9UdbDn2NciNjf4MEUBtNg9NySCwISfoJUi3Iwl2lWVVDxPpiwqeCy
kxXuRMLNScZvbZOBlva6qNSKdB48mW150yqMobVR4VITtrPwTR3aTc6iYsvkmXp3
G63KA007kNqmEFF1TPYYTyLBLc0WlMEs4F1gFGXL4st4ZrvOHMEyFwok1iqJ
-----END CERTIFICATE-----
 1 s:C = PL, ST = SL, L = Tychy, O = it.supra.tf, OU = IT, CN = vcenter.serba.local
   i:DC = local, DC = serba, CN = serba-DC1-CA
-----BEGIN CERTIFICATE-----
MIIGpzCCBI+gAwIBAgITLgAAACmSpTQ5IRDUEwAAAAAAKTANBgkqhkiG9w0BAQsF
ADBFMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFTATBgoJkiaJk/IsZAEZFgVzZXJi
YTEVMBMGA1UEAxMMc2VyYmEtREMxLUNBMB4XDTIwMDcxMjE1NTUwMFoXDTIyMDcx
MjE2MDUwMFowazELMAkGA1UEBhMCUEwxCzAJBgNVBAgTAlNMMQ4wDAYDVQQHEwVU
eWNoeTEUMBIGA1UEChMLaXQuc3VwcmEudGYxCzAJBgNVBAsTAklUMRwwGgYDVQQD
ExN2Y2VudGVyLnNlcmJhLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyHLNgqLJ7c+/6G657tO/pbdkxsUPvGvIAbCLEY7j7Ug6/0c6mC1rQ8R2
me4upGwhmKrl8moh4BAn5QhQUSM3KJQaTgo+a7vDpUFrs4cHMIPfApGR5tuKLv5B
4Sbr6zW/bZq8pxqpt/tosopXjF1nb3IulrTv6nFMq6sjKXYHTY3Gd3yxgky+tRa3
kFdvbyiMnF0NtJ5RMgfDo07O2ob0JWW/wg/mDeUOX3ofsYh9BQ7jOmGoiOtayA08
pGaIdvaI/15zw8MX7MtBxR1p3Ar0JYdzse/91ODDeUH3CCkt3hJdz+r1JBJS39v+
iuUD4Epx2CDaV8GGewAYTMosUlxZAQIDAQABo4ICaDCCAmQwDwYDVR0TAQH/BAUw
AwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFOLU6p14frk9ZYIzebfcuJhF
jwTLMDIGA1UdEQQrMCmBEnJhZG9zbGF3QHNlcmJhLm92aIITdmNlbnRlci5zZXJi
YS5sb2NhbDAfBgNVHSMEGDAWgBS7l5n/TyANX99lWhur0laIl0Ox1DCBxgYDVR0f
BIG+MIG7MIG4oIG1oIGyhoGvbGRhcDovLy9DTj1zZXJiYS1EQzEtQ0EsQ049ZGMx
LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD
Tj1Db25maWd1cmF0aW9uLERDPXNlcmJhLERDPWxvY2FsP2NlcnRpZmljYXRlUmV2
b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2lu
dDCB6AYIKwYBBQUHAQEEgdswgdgwgasGCCsGAQUFBzAChoGebGRhcDovLy9DTj1z
ZXJiYS1EQzEtQ0EsQ049QUlBLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENO
PVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9c2VyYmEsREM9bG9jYWw/Y0FD
ZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3Jp
dHkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vZGMxLnNlcmJhLmxvY2FsL29jc3AwGQYJ
KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDQYJKoZIhvcNAQELBQADggIBAIiXoJzn
zgWfaRYu0Syv+dtXgx0HBEbfhGTGaC/cOdU1fH0xnimxf0W0LRskeYuJ+NinbigW
hz1Ld1wmdw4Q00qirE5WGeKqy34bV16HW4UY5WA4JUCWwMxjZdLz5+ecdfXxlBPt
eGt+exJrBMRpiviBhYgEEs+XG7S3BSDRRnUWDXqn1bU0r27OicTt2hUZjNo7qoip
M3s0/xzrI73Bim01VZckFcXp1aR9HZpENZnjxcbNQUtoJ8Tww5sbf9vbotRWpQST
HzqGglofK6v7oV2Vc3AA6aU8dwR4a3eAEgEPO3bjLM0J3iAelWVy91aItt+qK60N
gy7fDIU9xQtDcBB6tJrIQPj4vpPC+5p3aXBxE3RjVELNlcVtGqPZG0dXHPYwiOW/
6+822zkIpAnxnYK9qjEpQ0elq+gZZrS4SemWXoYHqn1pPxat7kFwPo6iOLd8GqbR
/UFLuK+uOfbTYZuUCjQgMdJGJhLKosvyE0ypOOsyAQubdd8CM8cQ8PGykl7DI65B
9yupU7ZL8mezjmFvBXEQ6NpyQDTlp/tLz5M1RvyvLVEl96kt/icIK/Yhbi05Vgbc
Hhp6T8l27qZIIaq1tfHSf03IXwbCKVj8zwl2NIbgpFBA8qswjhzEr2vIIUiWxZDQ
m5ao8O7bT+SX3vHSwgwXHprtI8omTkK7RhPI
-----END CERTIFICATE-----
---
Server certificate
subject=C = US, ST = California, L = Palo Alto, O = VMware, OU = VMware Engineering, CN = vhost1.serba.local, emailAddress = vmca@vmware.com

issuer=C = PL, ST = SL, L = Tychy, O = it.supra.tf, OU = IT, CN = vcenter.serba.local

---
No client certificate CA names sent
Peer signing digest: SHA512
Peer signature type: RSA
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3238 bytes and written 446 bytes
Verification error: unable to get local issuer certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID:
    Session-ID-ctx:
    Master-Key: 9A160CF10EDEF17D1F972D3F2D1C0F5E9653F69C4D02F828EA9E05842945A246993339741750E7B3938CC9491C5A3D1C
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1594575144
    Timeout   : 7200 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
    Extended master secret: no
---

Wynika to z błędu, który jest w ESXi chyba nawet w wersji 6.0. Wygląda na to, że nawet w 7.0 jest z tym problem. Ten problem pojawia się zarówno dla vCenter jak i dla hostów ESXi. Na ten moment myślę, że prostszym rozwiązaniem jest rozpropagowanie certyfikatu vCenter po hostach za pomocą polityki GPO. Gdy pojawi się do tego osobny poradnik, postaram się go tutaj podlinkować. Zainstalowałem sobie taki certyfikat lokalnie na maszynie umieszczając certyfikat do folderu Pośrednie urzędy certyfikacji oraz zmieniłem w Firefoxie zmienną security.enterprise_roots.enable na true i wygląda na to, że to rozwiązuje problem:

Drugą kwestią jest to, że możemy zwrócić uwagę na to, że podmiot wystawiający certyfikat ma totalnie inne parametry, niż definiowaliśmy. Wynika to z tego, że w vCenter 7.0 kreator nie pyta nas o te dane i wykorzystuje domyślne ustawienia vCenter. Te wartości można znaleźć w ustawieniach zaawansowanych vCenter:

Z istotnych opcji są:

  • vpxd.certmgmt.certs.cn.country – państwo podmiotu, ustawiam PL,
  • vpxd.certmgmt.certs.cn.email – adres kontaktowy, ustawiam radoslaw@serba.ovh,
  • vpxd.certmgmt.certs.cn.localityName – nazwa miejscowości, ustawiam Tychy,
  • vpxd.certmgmt.certs.cn.organizationalUnitName – jednostka organizacyjna, ustawiam IT,
  • vpxd.certmgmt.certs.cn.organizationName – nazwa organizacji podmiotu, ustawiam it.supra.tf,
  • vpxd.certmgmt.certs.cn.state – województwo/region, ustawiam SL,
  • vpxd.certmgmt.certs.daysValidilość minut, po której możemy wystawić ponownie certyfikat dla hosta ESXi w minutach (domyślna to 24 godziny), jeśli kombinujemy z certyfikatami to warto ją tymczasowo zmniejszyć do kilku minut.

Przed zmianą tych wartości podmiot wyglądał tak:

Po zmianach wygląda tak:

Na koniec dodam, że istnieje też odrobinkę prostszy proces generowania (to jest od 7.0) i opisali to państwo w tym poradniku. Jedno jest pewne – to, co jest opisane powyżej na 100% działa, bo wdrażałem to kilka razy. Nie miałem okazji testować jeszcze opcji przez przeglądarkę.

EDIT: jednak da się bezpośrednio wrzucać pliki na vCenter przez WinSCP. Aby to zrobić, należy wcześniej podpiąć się przez SSH do maszyny i wykonać polecenia:

Po zakończeniu można przywrócić domyślny shell poleceniem:

chsh -s /bin/appliancesh root

Tworzenie środowiska testowego z użytkownikami w AD + tworzenie skrzynek dla nich w Exchange

Przeczytasz to w: 3 minut

Niedawno się tym zajmowałem i w sumie dobrze by było się podzielić takim skryptem. Jest on nieco zmodyfikowany w stosunku, do tego co znalazłem na tej stronie.

Na początku próbka danych, która powinna być zapisana w pliku CSV:

firstname;lastname;username;email;streetaddress;city;zipcode;state;country;department;password;telephone;jobtitle;company;ou
Miron;Trawiński;mtrawinski;mtrawinski@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Mikołaj;Staszewski;mstaszewski;mstaszewski@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Adam;Rekowski;arekowski;arekowski@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Joachim;Grabiński;jgrabinski;jgrabinski@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Norbert;Ewertowski;newertowski;newertowski@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Aureliusz;Wręczycki;awreczycki;awreczycki@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Heronim;Ambroży;hambrozy;hambrozy@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Piotr;Jaroszek;pjaroszek;pjaroszek@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Miłosz;Szcześniak;mszesniak;mszesniak@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Eustachy;Kowalewski;ekowalewski;ekowalewski@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Dorian;Kłopotowski;dklopotowski;dklopotowski@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Olgierd;Zaniewski;ozaniewski;ozaniewski@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Gracjan;Zambrzycki;gzambrzycki;gzambrzycki@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Fabian;Ciura;fciura;fciura@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local
Piotr;Skonieczny;pskonieczny;pskonieczny@serba.website;aleja Niepodległości 49;Tychy;43-100;śląskie;PL;Handlowy;Zaq12wsx!;32 776 33 33;Specjalista ds. handlowych;it.supra.tf;OU=Handlowy,OU=it.supra.tf,DC=serba,DC=local

Poniżej tworzenie OU oraz użytkowników w CSV (warto zwrócić uwagę, że pozycja Państwo jest zdefiniowana jako PL, a nie Polska ze względu na to, że w tym polu daje się Country Code.

<#Import active directory module for running AD cmdlets#>
Import-Module activedirectory

<#Create main OU#>
$baseDN = "DC=SERBA,DC=LOCAL"
$baseOU = "OU=it.supra.tf"
$baseOUstring = $baseOU + "," + $baseDN
<#New-ADOrganizationalUnit -Name "SUPRA" -Path $baseOU#>
if (Get-ADOrganizationalUnit -Filter "distinguishedName -eq '$baseOUstring'") {
    Write-Host "$baseOUstring already exists."
  } else {
    New-ADOrganizationalUnit -Name $baseOU -Path $baseDN
  }


<#Create OU's#>
$OUs = @("Dyrekcja","Handlowy","Marketing","Ksiegowosc","Rozwojowy","Prawny","Logistyczny","Techniczny")

<#Loop through each name of the OU to create them#>
foreach ($OUcreate in $OUs) {
    $fullOUstring = "OU=" + $OUCreate + "," + $baseOUstring
    Write-Output $fullOUstring
    if (Get-ADOrganizationalUnit -Filter "distinguishedName -eq '$fullOUstring'") {
        Write-Host "$OUcreate already exists."
      } else {
        New-ADOrganizationalUnit -Name $OUcreate -Path $baseOUstring
      }
}

<#Store the data from ADUsers.csv in the $ADUsers variable#>
$ADUsers = Import-csv -Delimiter ";" -Path .\bulk-users-polska.csv

<#Loop through each row containing user details in the CSV file#>
foreach ($User in $ADUsers)
{
	<#Read user data from each field in each row and assign the data to a variable as below#>
		
	$Username 	= $User.username
	$Password 	= $User.password
	$Firstname 	= $User.firstname
	$Lastname 	= $User.lastname
	$OU 		= $User.ou <#This field refers to the OU the user account is to be created in#>
    $email      = $User.email
    $streetaddress = $User.streetaddress
    $city       = $User.city
    $zipcode    = $User.zipcode
    $state      = $User.state
    $country    = $User.country
    $telephone  = $User.telephone
    $jobtitle   = $User.jobtitle
    $company    = $User.company
    $department = $User.department
    $Password = $User.Password


	<#Check to see if the user already exists in AD#>
	if (Get-ADUser -F {SamAccountName -eq $Username})
	{
		 <#If user does exist, give a warning#>
		 Write-Warning "A user account with username $Username already exist in Active Directory."
	}
	else
	{
		<#User does not exist then proceed to create the new user account
        Account will be created in the OU provided by the $OU variable read from the CSV file#>
		New-ADUser `
            -SamAccountName $Username `
            -UserPrincipalName "$Username@serba.local" `
            -Name "$Firstname $Lastname" `
            -GivenName "$Firstname" `
            -Surname "$Lastname" `
            -Enabled $True `
            -DisplayName "$Firstname $Lastname" `
            -Path "$OU" `
            -City "$city" `
            -Company "$company" `
            -State "$state" `
            -StreetAddress "$streetaddress" `
            -Country "$country" `
            -PostalCode "$zipcode" `
            -OfficePhone "$telephone" `
            -EmailAddress "$email" `
            -Title "$jobtitle" `
            -Department "$department" `
            -AccountPassword (convertto-securestring $Password -AsPlainText -Force) -ChangePasswordAtLogon $False -PasswordNeverExpires $True -CannotChangePassword $True
            
	}
}
Get-ADUser -Filter 'Name -like "*"' -SearchBase 'OU=it.supra.tf,DC=SERBA,DC=LOCAL' -Properties DisplayName | ForEach-Object {Set-ADUser $_ -Office 'SERBA Downtown'}
Get-ADUser -Filter 'Name -like "*"' -SearchBase 'OU=Techniczny,OU=it.supra.tf,DC=SERBA,DC=LOCAL' -Properties DisplayName | ForEach-Object {Set-ADUser $_ -Office 'SERBA Headquarters'}
Get-ADUser -Filter 'Name -like "*"' -SearchBase 'OU=Dyrekcja,OU=it.supra.tf,DC=SERBA,DC=LOCAL' -Properties DisplayName | ForEach-Object {Set-ADUser $_ -Office 'SERBA Headquarters'}

I na koniec tworzenie kont w Exchange dla tych użytkowników (istotne – ten skrypt musi być odpalony przez Exchange Management Shell):

Import-Module activedirectory
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn

<#adding everyone in that specified company#>
$users = Get-ADUser -Filter {company -eq "it.supra.tf"}
Write-Output $users
foreach($user in $users)
{
    Enable-Mailbox -Identity $user.SamAccountName
}

iRedMail, LDAP i migracja serwera pocztowego, z której się sporo nauczyłem

Przeczytasz to w: 16 minut

Ten post nie będzie do końca taki, jak wcześniej, bo niestety nie mam tyle czasu, by opisać całą instalację iRedMaila i tego, co robiłem. Ogólnie udało mi się zmigrować u klienta serwer pocztowy. Klient miał Debiana 6, trochę stary, użytkownicy lokalni, a nie w SQLu czy LDAPie (OpenLDAP lub AD) i trzeba było coś z tym zrobić. Był to jakiś pakiet, który bazował na Postfixie/Dovecot z interfejsem webowym Squirrel. Trzeba było coś z tym zrobić, więc ostatecznie zdecydowaliśmy się na migrację serwera na nowy, z Debianem 10 i celem był iRedMail – prosty pakiet z Postfixem i Dovecotem z podstawowym panelem administracyjnym. Wdrożyłem go z LDAPem z prostego powodu: jest szansa na to, że w przyszłości taki użytkownik będzie mógł wykorzystać logowanie z Active Directory jeśli przepnie się query z LDAPa do AD oraz każdemu użytkownikowi w AD doda się odpowiedni atrybuty, z których korzysta iRedMail.

Dlatego też jeśli chcecie się nauczyć stawiać iRedMaila – polecam sobie poczytać ich dokumentację. Jest tam naprawdę sporo ciekawych materiałów. Pomimo to są rzeczy, które nawet jeśli są w tej dokumentacji przykuły moją uwagę.

Migracja użytkowników do OpenLDAPa

Użytkownicy byli przechowywani lokalnie, więc mogłem znaleźć ich nazwy użytkowników, nazwy wyświetlane (Gecos) itd w pliku /etc/passwd. Ogólnie ten plik wygląda tak:

root:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeee
supra:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeeeeeeeee/:17604:0:99999:7:::
anotheruser:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeeeeeeeee.:17604:0:99999:7:::
editor:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeeeeeeeee.:17668:0:99999:7:::
test:$6$somesalt$aaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbb/cccccccccccccccccc/ddddddddddd.eeeeeeeeeeee.:18314:0:99999:7:::

Tutaj znalazłem informację jak tworzyć użytkowników w LDAPie z odpowiednimi atrybutami. Z tego pliku wyciągnęliśmy listę wszystkich użytkowników oraz Gecos. Wystarczy do tego Excel lub inny program pracujący z arkuszami kalkulacyjnymi, który jest w stanie zczytywać dane z plików, które mają oddzielone wartości za pomocą jakiegoś znaku (np. CSV). Na początku klikamy Z pliku tekstowego/CSV, następnie wskazujemy plik i wybieramy ogranicznik (znak oddzielający wartości, ang. delimiter), powinien być nim dwukropek.

Korzystam z Excel 2019 i on sam wykrył ten znak (musiałem jedynie zmienić kodowanie pliku na UTF-8), zmieniłem też pole Wykrywanie typu danych na Nie wykrywaj typów danych:

Jak widać, wszystko ładnie się zaimportowało:

Następnie należy trochę przerobić te dane. Składnia to:

mydomain.com, user2, plain_password, Michael Jordan, group1:group2,

W praktyce to powinno wyglądać tak:

Jak widać w stosunku do zrzutu ekranu wyżej, usunąłem przecinki po w nazwie wyświetlanej oraz poprzenosiłem wartości w kolejności. Kolumna F jest pusta, bo nie mam zdefiniowanych żadnych grup. W takiej sytuacji trzeba na końcu każdej linii po wyeksportowaniu pliku CSV dopisać spację i przecinek. Dodałem też te liczby i 5368709120 to jest quota (przydział rozmiaru skrzynki) w bajtach. 5368709120 daje nam 5 GB.

Zapisujemy plik w postaci CSV UTF-8 (w ogóle to jest dostępne tylko w Excel 2019, nie wiedzieć czemu):

Otrzymujemy to (otwieram takie pliki w Visual Studio Code):

Podmieńmy sobie najpierw średniki ; na przecinki ze spacją , :

Teraz musimy jakoś dodać te puste pola grup. Z faktu, że przypisałem wszystkim użytkownikom taką samą wielkość skrzynki, wykorzystam to, by dodać dodatkową wartość:

W ten sposób możemy wykorzystać taki plik CSV do zaimportowania użytkowników. Jak widać, nie przenoszę tutaj haseł tylko generuję nowe. Skorzystałem z random.org do wygenerowania hasełek, które wkleiłem do arkusza:

iRedMail dostarcza skrypty, które przygotowują za nas plik LDIF, który potem musimy wykorzystać do dodania użytkowników za pomocą polecenia ldapadd. Powinny być w folderze instalacyjnym iRedMaila, w folderze tools. Są dwa skrypty: create_mail_user_OpenLDAP.py i create_mail_user_OpenLDAP.sh. Ja skorzystałem z tego pierwszego, bo we wdrożeniu chciałem mieć katalogi użytkowników w konkretnym katalogu, a ten bashowy skrypt chyba na to nie pozwalał.

To, co trzeba sobie w tym skrypcie zmienić to:

# LDAP server address.
LDAP_URI = 'ldap://127.0.0.1:389'

# LDAP base dn.
BASEDN = 'o=domains,dc=example,dc=com'

# Bind dn/password
BINDDN = 'cn=Manager,dc=example,dc=com'
BINDPW = 'supersecretpassword'

# Storage base directory.
STORAGE_BASE_DIRECTORY = '/var/vmail/vmail1'

# Append timestamp in maildir path.
APPEND_TIMESTAMP_IN_MAILDIR = True

# Get base directory and storage node.
std = STORAGE_BASE_DIRECTORY.rstrip('/').split('/')
STORAGE_NODE = std.pop()
STORAGE_BASE = '/'.join(std)

# Hashed maildir: True, False.
# Example:
#   domain: domain.ltd,
#   user:   zhang (zhang@domain.ltd)
#
#       - hashed: d/do/domain.ltd/z/zh/zha/zhang/
#       - normal: domain.ltd/zhang/
HASHED_MAILDIR = True

Te zmienne definiują:

  • LDAP_URI – adres serwera LDAP, do którego się łączymy (jest on na serwerze localnie),
  • BASEDN – DN domeny, każdy element oddziela się przecinkiem w miejscu, gdzie jest kropka w nazwie, np. super.domena.com dzieli się na dc=super,dc=domena,dc=com, dopisujemy na początku o=domains wyjątkowo w tym polu,
  • BINDDN – użytkownik, na prawach którego wykonujemy operację, przy czym Manager jest kontem, które ma pełne prawa do modyfikowania wszystkiego, co jest w LDAPie, w dużym uproszczeniu to jest nazwa użytkownika + nazwa domeny, którą przedstawiałem wyżej, w tym polu trzeba poprawić domenę
  • BINDPW – hasło do konta Manager, znajdziemy je w katalogu instalacyjnym w pliku iRedMail.tips,
  • STORAGE_BASE_DIRECTORY – katalog bazowy, w którym znajdują się wszystkie skrzynki, ścieżka do katalogu użytkownika to STORAGE_BASE_DIRECTORY/<domena>/<folder-użytkownika>
  • APPEND_TIMESTAMP_IN_MAILDIR – jeśli true, foldery użytkownika wyglądają tak: supra-2020.04.22.17.19.56
  • HASHED_MAILDIR – tutaj ładnie jest opisane w skrypcie, w praktyce jak mamy włączony hash z ścieżką katalogu bazowego jak w skrypcie oraz dopisanie daty do nazwy folderu użytkownika to pełna ścieżka do skrzynki mailowej przykładowego użytkownika supra wygląda tak: /var/vmail/vmail1/domain.com/s/u/p/supra-2020.04.22.17.19.56

Jak mamy to, możemy sobie wrzucić plik CSV na serwer i go po prostu zaimportować. Warto sobie sprawdzić czy nazwy wyświetlane dobrze nam się czytają, by nie mieć żadnych znaków z niespodzianką (np. moje imię ma znak, który jest polski):

Jak widać, wszystko działa.

Jak to jest wszystko okej, odpalamy skrypt:

sudo python create_mail_user_OpenLDAP.py /home/supra/import.csv

Z jakiegoś powodu otrzymywałem ten błąd:

Traceback (most recent call last):
  File "create_mail_user_OpenLDAP.py", line 303, in <module>
    ldif_writer.unparse(dn, data)
  File "/usr/lib/python2.7/dist-packages/ldif.py", line 194, in unparse
    dn = dn.encode('utf-8')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 11: ordinal not in range(128)

Żeby rozwiązać to, należy wykorzystać program dos2unix, by przekonwertować plik:

$ dos2unix import.csv
dos2unix: konwersja pliku import.csv do formatu uniksowego...

Ewentualnie to można zrobić w Vimie poleceniem :set nobomb i zapisując plik. Teraz wynik dostaję taki:

< INFO > User data are stored in /home/supra/import.csv.ldif, you can verify it before importing it.
< INFO > You can import it with below command:
ldapadd -x -D cn=Manager,dc=example,dc=com -W -f /home/supra/import.csv.ldif

Plik wygląda tak:

dn: mail=supra@mydomain.com,ou=Users,domainName=mydomain.com,o=domains,dc=example,dc=com
changetype: add
objectClass: inetOrgPerson
objectClass: mailUser
objectClass: shadowAccount
objectClass: amavisAccount
mail: supra@mydomain.com
userPassword: {SSHA}wDV2pLwacxHOT8GpMRL3+wta9PfGGmVp
mailQuota: 5368709120
cn:: UmFkb3PFgmF3IFNlcmJh
sn: supra
uid: supra
storageBaseDirectory: /var/vmail
mailMessageStore: vmail1/mydomain.com/s/u/p/supra-2020.05.16.20.20.07/
homeDirectory: /var/vmail/vmail1/mydomain.com/s/u/p/supra-2020.05.16.20.20.07/
accountStatus: active
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: indexer-worker
enabledService: dsync
enabledService: quota-status
enabledService: mail
enabledService: smtp
enabledService: smtpsecured
enabledService: smtptls
enabledService: pop3
enabledService: pop3secured
enabledService: pop3tls
enabledService: imap
enabledService: imapsecured
enabledService: imaptls
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: lmtp
enabledService: sogo
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
shadowLastChange: 18398
amavisLocal: TRUE

dn: mail=mmarecki@mydomain.com,ou=Users,domainName=mydomain.com,o=domains,dc=example,dc=com
changetype: add
objectClass: inetOrgPerson
objectClass: mailUser
objectClass: shadowAccount
objectClass: amavisAccount
mail: mmarecki@mydomain.com
userPassword: {SSHA}L+5CB3x3tUyilp90aF9FFa9/Rab5FqAo
mailQuota: 5368709120
cn: Marek Marecki
sn: mmarecki
uid: mmarecki
storageBaseDirectory: /var/vmail
mailMessageStore: vmail1/mydomain.com/m/m/a/mmarecki-2020.05.16.20.20.07/
homeDirectory: /var/vmail/vmail1/mydomain.com/m/m/a/mmarecki-2020.05.16.20.20.07/
accountStatus: active
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: indexer-worker
enabledService: dsync
enabledService: quota-status
enabledService: mail
enabledService: smtp
enabledService: smtpsecured
enabledService: smtptls
enabledService: pop3
enabledService: pop3secured
enabledService: pop3tls
enabledService: imap
enabledService: imapsecured
enabledService: imaptls
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: lmtp
enabledService: sogo
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
shadowLastChange: 18398
amavisLocal: TRUE

dn: mail=dwarynska@mydomain.com,ou=Users,domainName=mydomain.com,o=domains,dc=example,dc=com
changetype: add
objectClass: inetOrgPerson
objectClass: mailUser
objectClass: shadowAccount
objectClass: amavisAccount
mail: dwarynska@mydomain.com
userPassword: {SSHA}XL1T9GV1SAqeRrsUx3K0C7eFSsTsm7AT
mailQuota: 5368709120
cn:: RGFyaWEgV2FyecWEc2th
sn: dwarynska
uid: dwarynska
storageBaseDirectory: /var/vmail
mailMessageStore: vmail1/mydomain.com/d/w/a/dwarynska-2020.05.16.20.20.07/
homeDirectory: /var/vmail/vmail1/mydomain.com/d/w/a/dwarynska-2020.05.16.20.20.07/
accountStatus: active
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: indexer-worker
enabledService: dsync
enabledService: quota-status
enabledService: mail
enabledService: smtp
enabledService: smtpsecured
enabledService: smtptls
enabledService: pop3
enabledService: pop3secured
enabledService: pop3tls
enabledService: imap
enabledService: imapsecured
enabledService: imaptls
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: lmtp
enabledService: sogo
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
shadowLastChange: 18398
amavisLocal: TRUE

dn: mail=adarecka@mydomain.com,ou=Users,domainName=mydomain.com,o=domains,dc=example,dc=com
changetype: add
objectClass: inetOrgPerson
objectClass: mailUser
objectClass: shadowAccount
objectClass: amavisAccount
mail: adarecka@mydomain.com
userPassword: {SSHA}ObU/Ydy4GUnT1hM3Ebmk+GE4hYPBUlVp
mailQuota: 5368709120
cn: Anna Darecka
sn: adarecka
uid: adarecka
storageBaseDirectory: /var/vmail
mailMessageStore: vmail1/mydomain.com/a/d/a/adarecka-2020.05.16.20.20.07/
homeDirectory: /var/vmail/vmail1/mydomain.com/a/d/a/adarecka-2020.05.16.20.20.07/
accountStatus: active
enabledService: internal
enabledService: doveadm
enabledService: lib-storage
enabledService: indexer-worker
enabledService: dsync
enabledService: quota-status
enabledService: mail
enabledService: smtp
enabledService: smtpsecured
enabledService: smtptls
enabledService: pop3
enabledService: pop3secured
enabledService: pop3tls
enabledService: imap
enabledService: imapsecured
enabledService: imaptls
enabledService: deliver
enabledService: lda
enabledService: forward
enabledService: senderbcc
enabledService: recipientbcc
enabledService: managesieve
enabledService: managesievesecured
enabledService: sieve
enabledService: sievesecured
enabledService: lmtp
enabledService: sogo
enabledService: shadowaddress
enabledService: displayedInGlobalAddressBook
shadowLastChange: 18398
amavisLocal: TRUE

Taki plik możemy zaimportować do iRedMaila za pomocą polecenia (parametr -w pozwala na podanie hasła w parametrze, -W powoduje, że wpisywane hasło nie jest widziane na ekranie):

ldapadd -x -D cn=Manager,dc=domain,dc=com -f /home/supra/import.csv.ldif -w haslodokontamanagera

W efekcie powinniśmy dostać to:

adding new entry "mail=mmarecki@etf2l.site,ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

adding new entry "mail=dwarynska@etf2l.site,ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

adding new entry "mail=adarecka@etf2l.site,ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

adding new entry "mail=tf2serv@etf2l.site,ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

adding new entry "mail=bots@etf2l.site,ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"

Możemy spotkać się z takim błędem:

adding new entry "mail=supra@etf2l.site,ou=Users,domainName=domain.com,o=domains,dc=domain,dc=com"
ldap_add: Already exists (68)

To po prostu oznacza, że dany użytkownik istnieje i jeśli wcześniej mieliśmy jakieś linijki o powodzeniu dodania użytkownika, to musimy usunąć wszystko wyżej wraz z użytkownikiem, który istnieje tak, że pierwszą linią będzie pierwsze pole następnego użytkownika. Każdy wpis jest oddzielony pustą linią i powinniśmy zachować takie odstępy, lecz na początku tego nie trzeba mieć.

Wyszukiwanie użytkowników w LDAPie w konsoli i w GUI

W konsoli jest to proste, wystarczy polecenie ldapsearch:

ldapsearch -b dc=etf2l,dc=site -H ldap://127.0.0.1 -D cn=vmail,dc=etf2l,dc=site -w secretvmailadminpassword -s sub "(&(mailMessageStore=*)(cn=postmaster))"

Parametry to:

  • -b – domena, dla której wykonujemy zapytanie
  • -H – host, do którego wysyłamy zapytanie
  • -D – konto, które ma prawa do wykonania tego typu zapytań w postaci DN
  • -w – hasło do tego konta
  • -s – nasze zapytanie

Zapytanie wyżej wyświetla daje w wyniku konta, które mają dowolną wartość wpisaną w atrybucie mailMessageStore (ścieżka do skrzynki pocztowej użytkownika) oraz wartość postmaster wpisaną w atrybucie cn (common name, z reguły jest unikalne). Poniżej zapytanie, które pyta tylko o konta z cn o wartości postmaster:

ldapsearch -b dc=etf2l,dc=site -H ldap://127.0.0.1 -D cn=vmail,dc=etf2l,dc=site -w secretvmailadminpassword -s sub "(cn=postmaster)"

Jeśli chodzi o GUI to tutaj trzeba trochę pokombinować. Widziałem komentarze na forach odradzające korzystania z phpLDAPadmin, więc skorzystałem z LAM (LDAP Account Manager).

Na początku ściągamy pakiet na naszą dystrybucję, w moim przypadku nie było w repozytorium, więc ściągnąłem sobie plik .deb z sieci i go zainstalowałem:

wget https://netix.dl.sourceforge.net/project/lam/LAM/7.2/ldap-account-manager_7.2-1_all.deb
sudo dpkg -i ldap-account-manager_7.2-1_all.deb
sudo apt -f install -y

W ten sposób LAM będzie zainstalowany. Następnie musimy go wystawić poprzez stronę i to ułatwia LAM samo w sobie, bo w /etc/ldap-account-manager/nginx.conf znajdziemy szablon lokalizacji, który możemy dodać do strony:

location /lam {
        index index.html;
        alias /usr/share/ldap-account-manager;
        autoindex off;

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $request_filename;
        }

        location ~ /lam/(tmp/internal|sess|config|lib|help|locale) {
                deny all;
                return 403;
        }

}

Trzeba tutaj poprawić linijkę, którą zaznaczyłem, bo pewnie nie używacie już takiej wersji PHP (OBY!). W domyślnej konfiguracji PHP aktualnej wersji pracuje pod adresem 127.0.0.1:9999, więc ta linijka powinna mieć fastcgi_pass 127.0.0.1:9999;. Ponadto dodałbym w tej lokalizacji takie dwie linijki, by ograniczyć dostęp do tej przeglądarki tylko z sieci, w której mamy możliwość administrowania wszystkim (w przykładzie będzie 192.168.10.0/24). Na lenia wrzuciłem konfigurację do /etc/nginx/sites-available/00-default-ssl.conf i dzięki temu dostanę się do strony wpisując w przeglądarce adres https://mail.domain.com/lam:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name mail.domain.com;

location /lam {
        allow 192.168.10.0/24;
        deny all;
        index index.html;
        alias /usr/share/ldap-account-manager;
        autoindex off;
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass 127.0.0.1:9999;
                fastcgi_param SCRIPT_FILENAME $request_filename;
        }

        location ~ /lam/(tmp/internal|sess|config|lib|help|locale) {
                deny all;
                return 403;
        }

}
    root /var/www/html;
    index index.php index.html;
    include /etc/nginx/templates/misc.tmpl;
    include /etc/nginx/templates/ssl.tmpl;
    include /etc/nginx/templates/iredadmin.tmpl;
    include /etc/nginx/templates/roundcube.tmpl;
    include /etc/nginx/templates/sogo.tmpl;
    include /etc/nginx/templates/netdata.tmpl;
    include /etc/nginx/templates/php-catchall.tmpl;
    include /etc/nginx/templates/stub_status.tmpl;
}

Po otwarciu strony musimy nieco zmienić konfigurację pod kątem logowania:

Następnie wybieramy Edytuj profile serwerowe:

W tym polu wpisujemy hasło lam i warto je zmienić:

W Ustawieniach głównych, sekcji Server settings ustawiamy odpowiedni DN domeny, do której się łączymy, przy okazji można zmienić język i strefę czasową:

Dodatkowo w Ustawieniach bezpieczeństwa definiujemy w polu Lista uprawnionych użytkowników definiujemy DN konta Manager:

Na końcu hasło do profilu warto sobie zmienić po to, by nikt nam tego profilu nie zmieniał:

Następnie możemy się zalogować wklejając hasło do konta Manager:

Ponadto warto sobie przejść do karty Typy kont i zmienić ustawienia Aktywuj rodzaje kont. Na tym etapie dałem sobie spokój z ukrywaniem mojej domeny, bo i tak do strony dostęp jest zablokowany:

W polach wpisałem:

  • Użytkownicy:
    • Sufiks LDAP: ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
    • Atrybuty listy: (to było za długie, by wpisać w liście)
uid;#cn;#accountStatus;#amavisLocal;#enabledService;#homeDirectory;#mail;#mailMessageStore;#mailQuota;#memberOfGroup;#objectClass;#shadowLastChange;#sn;#storageBaseDirectory;#userPassword
  • Grupy:
    • Sufiks LDAP: ou=Groups,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
    • Atrybuty listy: cn;#accountStatus;#enabledService;#mail;#mail;#objectClass

Po zmianach zapisujemy i logujemy się do konta Manager:

W ten sposób otrzymujemy ładną przeglądarkę kont:

Może nie tak ładną, wszystko przez pole enabledservice.

Tak czy siak mi lepiej się tego interfejsu używa poprzez Widok drzewa, który można znaleźć u góry, po prawej. W aktualnym interfejsie jest lepiej wyszukać coś, ale w tym drzewku łatwiej modyfikować i dodawać.

Dodajemy atrybuty poprzez pole Dodaj nowy atrybut po prawej stronie, następnie wybieramy z listy atrybut, który nas interesuje:

Potem jedynie wpisujemy, co chcemy i zapisujemy (przycisk jest na samym dole, Zaktualizuj obiekt). Tutaj przykład jeśli chcielibyśmy dodać użytkownikowi grupę po to, by po wysłaniu maila przez jakiegoś użytkownika na newsletter@etf2l.site otrzymywał wiadomości (inaczej mówiąc dodajemy użytkownika do wewnętrznej listy mailingowej):

Dodawanie aliasów

Na starym serwerze aliasy były przechowywane w pliku /etc/aliases, którego format był następujący:

suprovsky: supra
a.darecka: adarecka
ad: adarecka
admin: supra, adarecka

Po lewej znajduje się alias, po dwukropku znajduje się lista użytkowników, którzy mają otrzymywać wiadomości po odebraniu przez serwer wiadomości na alias, czyli np. wysyłka maila na admin@etf2l.site powoduje wysłanie maili do supra@etf2l.site oraz adarecka@etf2l.site.

W przypadku iRedMaila z OpenLDAP są dwie opcje, by to sobie dodać taki alias: przez LAM i przez polecenie ldapmodify z przygotowanym plikiem LDIF. W przypadku LAMa wystarczy, że dodamy nowy atrybut o nazwie shadowaddress i podamy po prostu pełny adres aliasu, czyli np. dla konta supra wartości atrybutu to suprovsky@etf2l.site oraz admin@etf2l.site.

Postać LDIF dla supra i adarecka wyglądałby następująco (trzeba pamiętać o dodaniu pustej linii pomiędzy wpisami):

dn: mail=supra@etf2l.site,ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
changetype: modify
add: shadowaddress
shadowaddress: suprovsky@etf2l.site
shadowaddress: admin@etf2l.site

dn: mail=adarecka@etf2l.site,ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
changetype: modify
add: shadowaddress
shadowaddress: a.darecka@etf2l.site
shadowaddress: ad@etf2l.site

Taki przygotowany LDIF zapisujemy do pliku, dajmy na to aliases.ldif i wrzucamy do LDAPa poleceniem:

ldapmodify -H ldap://127.0.0.1 -D cn=Manager,dc=etf2l,dc=site -f aliases.ldif -w 0PjBPdKWNgs3dWfux8BTK16wc6XCBF

W wyniku dostałem:

modifying entry "mail=supra@etf2l.site,ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site"

modifying entry "mail=adarecka@etf2l.site,ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site"

Czyli wszystko cacy.

Dodawanie grup (list mailingowych)

To akurat jest dosyć upierdliwe, bo jeśli chcemy dodać 1 grupę 500 użytkownikom to póki co nie znalazłem na to jakiejś magicznej sztuczki.

Ogólnie grupę tworzy się takim LDIFem (można go znaleźć tutaj):

dn: mail=all@etf2l.site,ou=Groups,domainName=mydomain.com,o=domains,dc=etf2l,dc=site
accountStatus: active
cn: demolist
enabledService: mail
enabledService: deliver
enabledService: displayedInGlobalAddressBook
mail: all@etf2l.site
objectClass: mailList
accesspolicy: domain

W tym LDIFie warto zwrócić uwagę na accesspolicy i poczytać w linku, który podałem wyżej. Wartość domain powoduje, że można na taką grupę wysyłać maile tylko z tej samej domeny. Dodajemy go tak:

ldapadd -x -D cn=Manager,dc=domain,dc=com -f /home/supra/newgroup.ldif -w haslodokontamanagera

Potem musimy do każdego obiektu, który ma należeć do wybranej grupy mailingowej (w tym przypadku all@etf2l.site) dodać atrybut z adresem mailowym takiej listy. Tutaj LDIF wygląda tak:

dn: mail=supra@etf2l.site,ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
changetype: modify
add: memberOfGroup
memberOfGroup: all@etf2l.site

I tutaj tak samo zmiany wprowadzamy poleceniem:

ldapmodify -H ldap://127.0.0.1 -D cn=Manager,dc=etf2l,dc=site -f addtogroup.ldif -w 0PjBPdKWNgs3dWfux8BTK16wc6XCBF

Modyfikowanie istniejących wpisów w LDAPie

To też sobie zapisałem, bo przydało mi się. ldapmodify można też używać w trybie interaktywnym, gdy się nie poda w argumencie -f pliku LDIF. Wtedy dane z w takim formacie podaje się wpisując je ręcznie i oddzielając enterami. Po wpisaniu całego wpisu należy zrobić linijkę przerwy i wykonać skrót Ctrl+D. To spowoduje wyjście z trybu interaktywnego i wykonanie zapytania do LDAPa. Przykład:

ldapmodify -H ldap://127.0.0.1 -D cn=Manager,dc=etf2l,dc=site -w 0PjBPdKWNgs3dWfux8BTK16wc6XCBF

Następnie dane, które wpisałem:

dn: mail=supra@etf2l.site,ou=Users,domainName=etf2l.site,o=domains,dc=etf2l,dc=site
changetype: modify
replace: memberOfGroup
memberOfGroup: newsletter@etf2l.site

W ten sposób z poprzednio ustawionego pola memberOfGroup na all@etf2l.site użytkownik supra będzie miał ustawioną grupę newsletter@etf2l.site.

Usunięcie domeny z pola logowania dla iRedMail (konkretnie SOGo)

Jest to tutaj opisane, ale nie dla SOGo. Do tego się odniosę. Trzeba edytować 1 plik, mianowicie /etc/sogo/sogo.conf, lecz przed tym trzeba sobie umożliwić jego modyfikację:

sudo chmod o+w /etc/sogo/sogo.conf

W pliku modyfikuję takie pola (podaję wartości, które ustawiam, nie wszystko dotyczy samego usunięcia z domeny, bo część to po prostu dobre praktyki):

SOGoLanguage = Polish;
SOGoForceExternalLoginWithEmail = NO;
SOGoTimeZone = "Europe/Warsaw";
SOGoUserSources = (
///zmieniamy tylko te pola///
bindDN = "cn=vmail,dc=etf2l,dc=site"; //usunąłem 'o=domains,' stąd
bindFields = (uid); //domyślna wartość to mail
)

Po zmianach restartujemy usługę poleceniem systemctl restart sogo i sprawa załatwiona.

Autokonfiguracja klientów pocztowych

Zbawienie dla administratorów. Wpisujesz nazwę użytkownika, maila i hasło. To wszystko. Brzmi zbyt pięknie, by było prawdziwe? Niekoniecznie musi! Są 2 gotowe formatki, które można wykorzystać i one są dla Microsoft Outlook oraz Mozilla Thunderbird. Sytuacja jest prosta: należy ustawić odpowiednie wpisy w DNSie i wystawić pliki na serwerze WWW.

Tutaj można zauważyć 2 wpisy CNAME autoconfig i autodiscover kierujące połączenia na domenę mail.etf2l.site, która jest innym CNAME, który kieruje na etf2l.site, a ten już kieruje na odpowiedni adres IP (to jest wpis A). To będzie nam potrzebne. Te dwa CNAME mają po prostu wskazywać serwer, na którym są formatki, które ma pobierać klient pocztowy. W dodatku nie musi być to bezpośrednio nasz serwer mailowy, ale zrobiłem tak, bo tak po prostu mi było łatwiej. Ponadto powinniśmy mieć wpis SRV _autodiscover._tcp, który kieruje na adres serwera, na którym jest taka formatka. W wartości powinniśmy wpisać 0 1 443 mail.etf2l.site, przy czym zmieniamy adres naszego serwera formatki na właściwy.

Wyjaśnimy sobie po co są te domeny. Domena autodiscover.etf2l.site (konkretnie adres https://autodiscover.etf2l.site/autodiscover/autodiscover.xml jest wykorzystywna przez Outlooka do wykrycia konfiguracji poczty. W sumie to nie musimy mieć nawet do tego subdomeny, bo na dobrą sprawę moglibyśmy wystawiać to na domenie etf2l.site bezpośrednio – to jest kwestia czysto seperacji konfiguracji. Strona autoconfig.etf2l.site jest zaś dla Thunderbirda – on łączy się na adres https://autoconfig.etf2l.site/mail/config-v1.1.xml i z niego zaciąga sobie konfigurację. Tutaj subdomena akurat jest potrzebna.

Outlook widząc domenę etf2l.site sprawdza wpis SRV, o którym wspomniałem by sprawdzić pod jakim adresem jest plik konfiguracyjny, następnie wysyła na adres wspomniany wyżej w POST taką zawartość:

 <?xml version="1.0" encoding="utf-8"?> 
 <Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"> 
 <Request>
 <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema> 
 <EMailAddress>supra@etf2l.site</EMailAddress> 
 </Request> 
</Autodiscover>

Jak można zauważyć, w polu EMailAddress jest adres użytkownika, który próbuje sobie skongurować Outlooka. Dla Outlooka nie wystawiamy autodiscover.xml w postaci gołego XMLa – możemy do tego wykorzystać skrypt w PHP, który wpisuje nam adres mailowy użytkownika w XML, a następnie nam go zwraca (musimy ten XML edytować podając prawidłowe dane do naszego serwera pocztowego):

<?php
//get raw POST data so we can extract the email address
$data = file_get_contents("php://input");
preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $data, $matches);

//set Content-Type
header("Content-Type: application/xml");
?>
<?php echo '<?xml version="1.0" encoding="utf-8" ?>'; ?>

<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>IMAP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>993</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName><?php echo $matches[1]; ?></LoginName>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
            </Protocol>
            <Protocol>
                <Type>POP3</Type>
                <Server>mail.etf2l.site</Server>
                <Port>995</Port>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
                <?php echo $LoginName; ?>
            </Protocol>
            <Protocol>
                <Type>SMTP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>465</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName><?php echo $matches[1]; ?></LoginName>
                <SPA>off</SPA>
                <AuthRequired>on</AuthRequired>
                <UsePOPAuth>off</UsePOPAuth>
                <SMTPLast>off</SMTPLast>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>

Warto wziąć pod uwagę, że jako SMTP określiłem połączenie SSL/TLS na porcie 465 – w większości użytkownicy będą woleli korzystać ze STARTTLS na porcie 587. Korzystałem z 465 w ramach testu, bo UPC nie blokuje tego portu 😂

W praktyce ze STARTTLSem na 587 powinniśmy podmienić w ten sposób sekcję Protocol:

            <Protocol>
                <Type>SMTP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>587</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName><?php echo $matches[1]; ?></LoginName>
                <SPA>off</SPA>
                <Encryption>TLS</Encryption>
                <AuthRequired>on</AuthRequired>
                <UsePOPAuth>off</UsePOPAuth>
                <SMTPLast>off</SMTPLast>
            </Protocol>

W naszym przykładzie będziemy przechowywać te formatki w katalogu /var/www/autodiscover (może być to dowolna inna lokalizacja, po prostu przyjęło się, że w /var/www z reguły są pliki wystawiane przez serwer HTTP). Ten plik będzie nazwany jako autodiscover.php. Do tego config, który jest potrzebny dla nginxa, by wystawiał dostęp dla tej domeny i do tego pliku (umieściłem go w /etc/nginx/sites-available/autodiscover.etf2l.site:

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name autodiscover.etf2l.site;
    root /var/www/autodiscover;
    index index.php;
        include /etc/nginx/templates/ssl.tmpl;
        error_log /var/log/nginx/autodiscover-error.log;
        access_log /var/log/nginx/autodiscover-access.log combined;
        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
    location ~ /(?:a|A)utodiscover/(?:a|A)utodiscover.xml {
        root /var/www/;
        try_files /autodiscover/autodiscover.php =404;
        fastcgi_pass 127.0.0.1:9999; #w tym miejscu jest prawidłowa wartość dla serwera z iredmailem
        fastcgi_index  index.php;
        include        fastcgi.conf;
        fastcgi_param SERVER_ADDR "";
        fastcgi_param REMOTE_ADDR $http_x_real_ip;
    }
}

Następnie należy dodać sobie symlink takiego configa do /etc/nginx/sites-enabled, by był wykorzystywany przez nginxa i warto też wykonać test konfiguracji, by sprawdzić, czy nie wkradł nam się do configa jakiś błąd przed restartem usługi. Jeśli taki będzie i zrestartujemy usługę, ta się nie uruchomi po zatrzymianiu i to może dla nas być problem. Test wykonuje się poleceniem nginx -t. Taki jest poprawny wynik testu:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Koniec końców linkuję konfig, wykonuję test i restartuję usługę tak:

cd /etc/nginx/sites-enabled
ln -s ../sites-available/autodiscover.etf2l.site
nginx -t
systemctl restart nginx

Następnie możemy sobie przetestować, czy taka formatka nam działa wykonując ręczny test za pomocą cURLa. Musimy zapisać sobie wspomniany na początku request do pliku. Nazwijmy go req.xml, następnie wykonujemy następujące polecenie:

curl -X POST file:/home/supra/req.xml https://autodiscover.etf2l.site/autodiscover/autodiscover.xml

W wyniku otrzymałem:

<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
  <Request>
    <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
    <EMailAddress>supra@etf2l.site</EMailAddress>
  </Request>
</Autodiscover>
<?xml version="1.0" encoding="utf-8" ?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>IMAP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>993</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName></LoginName>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
            </Protocol>
            <Protocol>
                <Type>POP3</Type>
                <Server>mail.etf2l.site</Server>
                <Port>995</Port>
                <SPA>off</SPA>
                <SSL>on</SSL>
                <AuthRequired>on</AuthRequired>
                            </Protocol>
            <Protocol>
                <Type>SMTP</Type>
                <Server>mail.etf2l.site</Server>
                <Port>465</Port>
                <DomainRequired>off</DomainRequired>
                <LoginName></LoginName>
                <SPA>off</SPA>
                <AuthRequired>on</AuthRequired>
                <UsePOPAuth>off</UsePOPAuth>
                <SMTPLast>off</SMTPLast>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>

To oznacza, że wszystko się zgadza. Z poziomu Outlooka wygląda to tak:

W przypadku Thunderbirda jest podobnie, lecz nie trzeba robić sztuczek z PHPem – wystarczy w odpowiedni sposób przygotować plik XML (umieszczając go w /var/www/autodiscover) oraz umieścić do niego pasujący plik konfiguracyjny do nginxa (oczywiście na Apache’u też to można zrobić, ale dla mnie Apache śmierdzi i nie będę go używał):

<?xml version="1.0" encoding="UTF-8"?>

<clientConfig version="1.1">
    <emailProvider id="etf2l.site">
        <domain>mail.etf2l.site</domain>
        <displayName>Mail</displayName>
        <displayShortName>Mail</displayShortName>
        <incomingServer type="imap">
            <hostname>mail.etf2l.site</hostname>
            <port>993</port>
            <socketType>SSL</socketType>
            <authentication>password-cleartext</authentication>
            <username>%EMAILADDRESS%</username>
        </incomingServer>
        <incomingServer type="imap">
            <hostname>mail.etf2l.site</hostname>
            <port>143</port>
            <socketType>STARTTLS</socketType>
            <authentication>password-cleartext</authentication>
            <username>%EMAILADDRESS%</username>
        </incomingServer>
        <outgoingServer type="smtp">
            <hostname>mail.etf2l.site</hostname>
            <port>465</port>
            <socketType>SSL</socketType>
            <authentication>password-cleartext</authentication>
            <username>%EMAILADDRESS%</username>
        </outgoingServer>
        <outgoingServer type="smtp">
            <hostname>mail.etf2l.site</hostname>
            <port>587</port>
            <socketType>STARTTLS</socketType>
            <authentication>password-cleartext</authentication>
            <username>%EMAILADDRESS%</username>
        </outgoingServer>
    </emailProvider>
</clientConfig>

W tym XMLu kolejność protokołów ma znaczenie, wiec jeśli chcemy w pierwszej kolejności używać portu 587 zamiast 465 to musimy zamienić sekcje outgoingServer miejscami. Następnie config do nginxa wygląda tak:

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name autoconfig.etf2l.site;
        location ^~ /mail {
        alias /var/www/autodiscover;
        try_files $uri =404;
}
    root /var/www/autodiscover;
    index index.php;
        include /etc/nginx/templates/ssl.tmpl;
        error_log /var/log/nginx/autodiscover-error.log;
        access_log /var/log/nginx/autodiscover-access.log combined;

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
}

Po zrobieniu symlinka do tego configa w /etc/nginx/sites-enabled, zrobieniu testu i zrestartowaniu nginxa możemy zobaczyć jak nasz Thunderbird się sam konfiguruje:

Jest też opcja, by móc automatycznie konfigurować sprzęt Apple’a, ale jestem zbyt leniwy, by to przetestować. Jest to opisane tutaj.

Zabezpieczenie się przed niepowołanym dostępem do administracji

Jest kilka rzeczy, które powinno się zrobić z mojego punktu widzenia, by zminimalizować ryzyko, że ktoś niepowołany wejdzie na jakąś stronę. Po pierwsze, należy obciąć dostęp do LDAP Account Managera/phpLDAPadmin (jeśli zainstalowany) w nginxie, następnie to należy powtórzyć dla lokalizacji w plikach:

  • /etc/nginx/templates/adminer.tmpl,
  • /etc/nginx/templates/iredadmin.tmpl,
  • /etc/nginx/templates/iredadmin.tmpl-subdomain.tmpl,
  • /etc/nginx/templates/netdata.tmpl,
  • /etc/nginx/templates/netdata-subdomain.tmpl.

Przykład w /etc/nginx/templates/iredadmin.tmpl:

# Settings for iRedAdmin.

# static files under /iredadmin/static
location ~ ^/iredadmin/static/(.*) {
    alias /opt/www/iredadmin/static/$1;
}

# Python scripts
location ~ ^/iredadmin(.*) {
    allow 192.168.10.0/24;
    deny all;
    rewrite ^/iredadmin(/.*)$ $1 break;

    include /etc/nginx/templates/hsts.tmpl;

    include uwsgi_params;
    uwsgi_pass 127.0.0.1:7791;
    uwsgi_param UWSGI_CHDIR /opt/www/iredadmin;
    uwsgi_param UWSGI_SCRIPT iredadmin;
    uwsgi_param SCRIPT_NAME /iredadmin;

    # Access control
    #allow 127.0.0.1;
    #allow 192.168.1.10;
    #allow 192.168.1.0/24;
    #deny all;
}

# iRedAdmin: redirect /iredadmin to /iredadmin/
location = /iredadmin {
    rewrite ^ /iredadmin/;
}

# Handle newsletter-style subscription/unsubscription supported in iRedAdmin-Pro.
location ~ ^/newsletter/ {
    rewrite /newsletter/(.*) /iredadmin/newsletter/$1 last;

Po zmianach wiadomo, restarcik nginxa się przyda: systemctl restart nginx.

Poza tym powinno się nasłuchiwać połączenia serwera SSH tylko i wyłącznie z podsieci administracyjnej, powinno się wyłączyć logowanie na roota po SSH oraz wyłączyć logowanie za pomocą haseł i przerzucić się na klucze publiczne zmieniając plik /etc/ssh/sshd_config (zamieszczam tylko istotny fragment):

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
PermitRootLogin no
PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no

Dostęp z innych podsieci możemy załatwić za pomocą iptables:

iptables -A INPUT -p tcp --dport 22 --source 192.168.10.0/24 -j ACCEPT

Warto też się upewnić, że domyślna polityka INPUT dla iptables to DROP (to oznacza, że dla każdego ruchu niezdefiniowanego w regułach iptables w sekcji INPUT jest wykonywany DROP, czyli brak odpowiedzi):

sudo iptables -L -v
[sudo] password for supra:
Chain INPUT (policy DROP 1803K packets, 167M bytes)

Do iptables warto mieć opcję zapisywania konfiguracji i można znaleźć o tym fajny poradnik tutaj.

Integracja SSO interfejsu iRMC w serwerach Fujitsu z domeną Active Directory wraz z certyfikatem SSL

Przeczytasz to w: 8 minut

Tym razem postaram się opisać pokrótce jak krok po kroku sprawić, że możemy logować się kontami z AD do interfejsu konsoli do zdalnego zarządzania serwerem iRMC. iRMC jest narzędziem out-of-band management serwera, dzięki czemu możemy z poziomu takiej witryny sprawdzić, czy serwer jest włączony, czy jego wszystkie komponenty są sprawne lub też nie czy też zdalnie zainstalować system operacyjny lub też zdalnie go obsługiwać. Co ważne, taki interfejs daje nam taką przewagę nad RDP/VNC, że możemy mieć dostęp do serwera będąc np. w ustawieniach BIOS serwera, więc te rozwiązanie pracuje niezależnie od systemu operacyjnego, który pracuje na hoście.

EDIT: Zdecydowałem się rozszerzyć nieco ten post o certyfikat SSL i wykorzystanie LDAP over SSL. Staram się to teraz wdrażać wszędzie, więc tutaj też powiem o tym więcej.

Certyfikat SSL

Zanim zaczniemy, musimy mieć wcześniej wdrożony urząd certyfikacji (na przykład dzięki usłudze certyfikatów Active Directory) i to jest coś, czego tutaj nie będę omawiał. Zanim wygenerujemy żądanie podpisania certyfikatu, warto się zastanowić jaka będzie nasza nazwa hosta. W moim przypadku jest to irmc-vhost1.serba.local ze względu na to, że mogę zawsze mieć wiele serwerów z iRMC, przez co same irmc.serba.local mogłoby być kiepskim rozwiązaniem po kupnie drugiej maszyny. Na początku zdefiniowałem w DNS przypisany do adresu iRMC, by można go było potem używać zamiast adresu IP. Efekt widać poniżej:

Następnie za pomocą OpenSSL stworzyłem klucz oraz wygenerowałem żądanie certyfikatu. Nie będę się o tym rozpisywał – opisałem cały proces tutaj. W stosunku, co jest w podlinkowanym poradniku należy zmienić jedynie CN oraz DNS.1 na irmc-vhost1.serba.local. Po wygenerowaniu CSRki można bić do serwera i wygenerować certyfikat SSL. Jeśli mamy zainstalowaną funkcję urzędu certyfikacji o nazwie Rejestracja w sieci Web dla urzędu certyfikacji, możemy podpisać żądanie przez stronkę urzędu, co zalecam robić, bo jest po po prostu proste i przyjemne. Adres takiej strony to http://<adres-ca>/certsrv. W moim przypadku jest to https://dc1.serba.local/certsrv (zmieniłem kilka ustawień w IIS, by mieć połączenie po HTTPS ;))

Na początku należy się zalogować swoim kontem administracyjnym w AD:

Następnie należy wybrać Żądanie certyfikatu.

Następnie wybieramy zaawansowane żądanie certyfikatu.

Na tym etapie musimy otworzyć nasz plik CSR w jakimś edytorze tekstu, skopiować zawartość i wkleić w pole żądania. Ponadto, musimy wybrać szablon certyfikatu, dzięki czemu określamy przeznaczenie certyfikatu, który generujemy. To, co nasz interesuje to Serwer sieci Web. Po tym klikamy Prześlij >.

Po tym pobieramy certyfikat w formacie Base-64.

Ponadto, musimy pobrać certyfikat urzędu certyfikacji, co możemy zrobić na stronie głównej urzędu poprzez opcję Pobierz certyfikat urzędu certyfikacji, łańcuch certyfikatów lub listę CRL, a następnie mając zaznaczoną metodę kodowania Base 64, następnie klikając Pobierz certyfikat urzędu certyfikacji.

Następnie musimy się zalogować do interfejsu iRMC i wgrać certyfikaty urzędu certyfikacji oraz certyfikatu SSL wraz z kluczem prywatnym, który wykorzystaliśmy przy wygenerowaniu CSRki. W Tools > Certificates > Current CA Certificate for CAS and SMTP należy kliknąć Load from File (stronę trzeba rozwinąć i znajdziemy przycisk w dolnej części karty po prawej stronie.

Następnie należy kliknąć Select…, wybrać plik CA i po tym kliknąć Upload. W ten sposób mamy zainstalowany certyfikat CA. Następnie wrzucamy certyfikat w Certification Authorities for eLCM rozwijając opcje, klikając Add, następnie w From file wybierając plik i zatwierdzając przyciskiem Add:

Efekt końcowy wygląda tak:

Na końcu rozwijając Current SSL/TLS Certificate należy kliknąć Load from File, a następnie w polu SSL/TLS public key dodać plik wygenerowanego certyfikatu SSL, a w SSL/TLS private key należy umieścić klucz prywatny, którym wygenerowaliśmy CSRkę, to wygląda tak:

Po tym klikamy Upload. Jesteśmy ponadto informowani, że należy wykonać restart iRMC w celu zastosowania zmian, więc klikamy Reboot iRMC.

No i czekamy.

Przed restartem systemu strona była wyświetlana jako niezaufana:

Po restarcie mamy wynik osiągnięty:

Teraz można przejść do integracji.

Integracja SSO

Do integracji należy skorzystać z drugiej płyty ServerView, którą można ściągnąć na stronie producenta po wybraniu swojego modelu urządzenia pod tym linkiem.

Następnie po otwarciu pliku .iso znajdującego się w Archiwum należy odnaleźć plik SVS_LdapDeployer.zip w ścieżce <litera-obrazu>:\SVSSoftware\Software\RemoteView\iRMC_Tools\SVS_LdapDeployer. Kopiujemy go na komputer, na którym:

  • Jesteśmy zalogowani na konto administracyjne w domenie i mamy do niej dostęp (najlepiej nie logować się bezpośrednio na kontrolerze domeny),
  • Mamy zainstalowane Java Runtime w wersji co najmniej 1.5 (można je ściągnąć stąd).

Po rozpakowaniu archiwum otwieramy zawartość i kopiujemy plik Configuration_InitialDeploy_ActiveDirectory.xml do katalogu, w którym znajduje się plik SVS_LdapDeployer.jar.

Następnie edytujemy wspomniany plik .xml. W następującej linii poprawiamy adres na adres naszego kontrolera domeny. Jeśli na serwerze nie używa się SSLa do szyfrowania komunikacji, powinno się zmienić port na 389 i zmienić wpis SSLEnabled na false:

<DirectoryService>ldap://192.168.10.156:636</DirectoryService>

Po zmianie:

<DirectoryService>ldap://dc1.serba.local:389</DirectoryService>
<SSLEnabled>false</SSLEnabled>

Następnie zmieniamy DN w tej linii na DN naszej domeny (w moim przypadku serba.local):

<root>dc=mycompany,dc=net</root>

Po zmianie:

<root>dc=serba,dc=local</root>

Zmieniamy konto administracyjne, z którego korzystamy do autoryzacji (opcjonalne), na pewno trzeba poprawić domenę na właściwą:

<username>administrator@mycompany.net</username>

Po zmianie:

<username>administrator@serba.local</username>

Następnie najlepiej usunąć ten wpis:

<password>encrypted_user_password</password>

Dzięki temu programik do tworzenia drzewa OU ServerView spyta nas o hasło przed rozpoczęciem pracy.
Następnie w sekcji Data mamy do zdefiniowania role:

        <Roles>
            <Role name ="Administrator" >
                <Privilege name ="IpmiLanOem" />
                <Privilege name ="IpmiSerialOem" />
                <Privilege name ="iRMCsettings" />
                <Privilege name ="RemoteStorage" />
                <Privilege name ="UserAccounts" />
                <Privilege name ="VideoRedirection" />
                <Privilege name ="CfgConnectionBlade" />
                <Privilege name ="RedfishAdmin"/>
            </Role> 
            
            <Role name ="Maintenance">
                <Privilege name ="IpmiLanOem" />
                <Privilege name ="IpmiSerialOem" />
                <Privilege name ="iRMCsettings" />
                <Privilege name ="VideoRedirection" />
                <Privilege name ="RedfishOperator"/>
            </Role>
            
            <Role name ="Operator">
                <Privilege name ="IpmiLanOperator" />
                <Privilege name ="IpmiSerialOperator" />
                <Privilege name ="VideoRedirection" />
                <Privilege name ="RedfishOperator"/>
            </Role>
            
            <Role name ="Monitor">
                <Privilege name ="IpmiLanUser" />
                <Privilege name ="IpmiSerialUser" />
                <Privilege name ="RedfishReadOnly"/>
            </Role>
            
            <Role name ="CustomRole">
                <Privilege name ="IpmiLanUser" /> 
                <Privilege name ="IpmiSerialUser" /> 
                <Privilege name ="VideoRedirection" /> 
            </Role>
        </Roles>

Z reguły nie ma potrzeby posiadania tylu ról, dlatego usuwam wszystkie poza adminem, docelowo wygląda to tak:

        <Roles>
            <Role name ="Administrator" >
                <Privilege name ="IpmiLanOem" />
                <Privilege name ="IpmiSerialOem" />
                <Privilege name ="iRMCsettings" />
                <Privilege name ="RemoteStorage" />
                <Privilege name ="UserAccounts" />
                <Privilege name ="VideoRedirection" />
                <Privilege name ="CfgConnectionBlade" />
                <Privilege name ="RedfishAdmin"/>
            </Role>
        </Roles>

Potem, w sekcji Departments zmienam w Department name na nazwę domeny bez końcówki, więc w tym przypadku ustawiłbym serba, poza tym wyrzucam usunięte role poniżej:

        <Departments>
            <!-- 
            # any number of departments possible
            # !!! Name of Department and associated roles need to be changed !!!
            -->
            <Department name ="DeptX">
                <!-- 
                # List of associated roles.
                # any number of roles, but only from roles defined above
                -->
                <Role name ="Administrator" /> 
                <Role name ="Maintenance" /> 
                <Role name ="Monitor" /> 
                <Role name ="CustomRole" /> 
            </Department>
        </Departments>

Po zmianie:

        <Departments>
            <!-- 
            # any number of departments possible
            # !!! Name of Department and associated roles need to be changed !!!
            -->
            <Department name ="serba">
                <!-- 
                # List of associated roles.
                # any number of roles, but only from roles defined above
                -->
                <Role name ="Administrator" /> 
            </Department>
        </Departments>

Po wykonaniu zmian zapisuję plik i otwieram konsolę PowerShell lub Wiersz poleceń z uprawnieniami administracyjnymi:

Po tym przechodzę do ścieżki z programem SVS_LdapDeployer i odpalam polecenie:

java -jar SVS_LdapDeployer.jar -deploy Configuration_InitialDeploy_ActiveDirectory.xml

Zostaniemy zapytani o hasło i podczas wpisywania jest ono widoczne.

Po wykonaniu tej czynności powinniśmy mieć gotowe drzewko w AD.

Teraz należy utworzyć konto, które będzie wykorzystywane w iRMC w celu sprawdzania kto jest członkiem tej grupy Administrator, a następnie należy dodać je do tej grupy wraz ze wszystkimi kontami użytkowników, które mają mieć dostęp do iRMC. Należy dodać konta użytkowników, a nie grupy ze względu na to, że iRMC nie obsługuje z jakiegoś powodu dziedziczenia członkostwa w grupach. Na potrzeby usługi utworzyłem konto serviceacc:

Nastęonie zanim zacznie się konfigurować profil domeny należy skonfigurować serwery DNS dla naszej domeny w Settings > Network Management > DNS:

  • Enable DNS: zaznaczone
  • DNS Configuration: Obtain from DHCP odznaczone
  • DNS Domain: po prostu nazwa naszej domeny
  • DNS Search Path: możemy też podać nazwę naszej domeny, dzięki temu dc1.serba.local == dc1. Nie wiem w sumie jak można to wykorzystać, ale ogólnie to jest najlepsza opcja konfiguracji.
  • DNS Server 1, 2 i 3: tutaj podajemy adresy DNS, z których korzystamy.

W moim przypadku efekt wygląda tak:

Po dodaniu kont do grupy musimy zdefiniować ustawienia w iRMC, dzięki któremu iRMC będzie wiedziało jak komunikować się z AD. Po zalogowaniu się do iRMC otwieramy u góry kartę Settings, następnie User Management po lewej stronie i z niej rozwijamy ustawienia Lightweight Directory Access Protocol (LDAP).

Następnie wpisujemy tutaj dane (Backup LDAP Server jest opcjonalny, jeśli posiadasz drugi kontroler domeny to warto go tu wpisać):

  • Global Configuration
    • Enable LDAP: zaznaczone
    • Enable LDAP SSL/TLS: wedle preferencji, w moim przypadku zaznaczone
    • Disable Local Login: ta opcja wyłącza możliwość logowania się z kont lokalnych, odradzam zaznaczanie jej
    • Directory Server Type: Active Directory
  • Primary LDAP Server
    • Server: dc1.serba.local
    • Network Port: 389
    • SSL/TLS Network Port: 636
  • Backup LDAP Server
    • Server: dc2.serba.local
    • Network Port: 389
    • SSL/TLS Network Port: 636
  • Directory Configuration
    • Authorization Type: ServerView LDAP Groups with Authorization Settings on LDAP Server
    • Department Name: serba
    • Domain Name: serba.local
    • Groups Directory as Sub-tree from Base DN: (puste)

W tej konfiguracji wyżej korzystam z FQDN serwerów – warto o tym pamiętać, by ustawić w konfiguracji serwer DNS tak, by wskazywał na nasze kontrolery domeny, dzięki czemu nazwy będą rozwiązywały się poprawnie. Potem przechodzimy do sekcji, w której określamy użytkownika, z którego korzystamy do komunikacji z AD i pole obiektu AD, z którego korzystamy:

Tutaj definiujemy:

  • Access Configuration
    • Authentication LDAP Username: serviceacc
    • Authentication LDAP Password: *********
    • Confirm Password: *********
    • Principal User DN: (puste)
    • Append Base DN to Principal User DN: odznaczone
    • Enable Enhanced User Login: zaznaczone (opcjonalne)
    • User Login Search filter: (&(objectClass=person)(sAMAccountName=%s))

Pole obiektu AD, po którym iRMC wyszukuje użytkownika domyślnie to cn, dlatego ja to zmieniam na sAMAccountName, bo wtedy korzystamy z takiego samego loginu jak do Windowsa. Takie pole można sobie sprawdzić w przystawce Użytkownicy i komputery usługi Active Directory mając zaznaczoną opcje Widok > Opcje zaawansowane. Poniżej przykład z zaznaczonym polem userPrincipalName:

W ten sposób można się logować na konta z Active Directory. Warto sobie w takiej sytuacji zmienić hasło dla konta lokalnego admin na długie ze względów bezpieczeństwa.

Efekt końcowy wygląda następująco:

UPDATE: Dzisiaj w trakcie wdrożenia na Windowsie Server 2019 Essentials miałem taki problem, że po wykonaniu instrukcji powyżej nie byłem w stanie stworzyć sobie drzewka w AD i otrzymywałem błąd:

- The keystore location is not accessible.
- The keystore's password is not correct.
- The keystore you specified is not the one generated during encryption.

Please try again or reset the password.

Rozwiązanie jest takie, by podać login i hasło do konta, którym się autoryzujemy w parametrach w plaintext:

java -jar SVS_LdapDeployer.jar -deploy Configuration_InitialDeploy_ActiveDirectory.xml -username administrator@serba.local -password Zaq12wsx!

Zawsze polecam zmieniać hasło na takie, które można pokazać przed innymi, a potem zmienić z powrotem na bezpieczne; w innym wypadku róbmy takie operacje będąc w zaufanym gronie osób (to znaczy często w osobności).

Druga rzecz to jest to, że w katalogu z szablonami są pliki Configuration_InitialDeploy_ActiveDirectory.xml i Configuration_InitialDeploy_AD.xml. W tym poradniku korzystałem z tego pierwszego.