Author Archives: admin

Extend a debian/ubuntu partition on a virtual machine.

This is howto extend a virtual machine drive running Debian / Ubuntu
1. First you need to make sure that there are no snapshot of the VM. If there are snapshot, you can extend the drive in either vmWare or Hyper-V.
2. If the server is running Hyper-v, you can’t extend an IDE drive. If it are an IDE device, you need to turn of the computer first.
3. Make sure that the partition is not an extended partition. If it are you can still extend it, but then this guide won’t work for you. Run fdisk -l /dev/sdX
4. Make sure that the drive is not an LVM storage. Then you can’t used this guide.

The above image, showes that there are an extend partition.

After you have checked, that there are no snapshot, the drive is not an IDE and it the last partition on the drive that needed to extend. Then goes to yours hypervisor and extend the drive, with the amount of storage you will like to have the drive extend with.

Then back on the linux server, install the package cloud-guest-utils, with this command

apt install cloud-guest-utils

Then run these commands:

ls /sys/class/scsi_host/ | while read host ; do echo "- - -" > /sys/class/scsi_host/$host/scan ; done
ls /sys/class/scsi_device/ | while read host ; do echo 1 > /sys/class/scsi_device/$host/device/rescan ; done

This will rescan the SCSI bus for new drive and drive extension.

After you have run the rescan you should extend the partition you want to extend

growpart /dev/sda 2

This commands will extend partition 2 on /dev/sda with the amount of free space on the drive, after partition 2.

After the partition have been extended, you need to extend the filesystem. This can be done by resize2fs

resize2fs /dev/sda2


Selfsign with Windows Certification Authority

If you just create a certificate, and it signed by a Windows Certification Authority, the certs is working just fine in the old Internet Explorer, but Chrome/Firefox and the new Edge browser will failed, with Common Name invalid, the precise error in Chrome is: NET::ERR_CERT_COMMON_NAME_INVALID.

This is because a normal certificate request, does not included a subject alternative name.
So to fix this you new to request the certficate, by an inf file instead

So first create a new Certreq.inf file and paste this into it:

;----------------- request.inf -----------------
[Version]

Signature="$Windows NT$"

[NewRequest]

Subject = "CN=kennethdalbjerg.dk, OU=Hosting, O=KennethDalbjerg, L=DK, S=DK, C=DK" ; replace attribues in this line
KeySpec = 1
KeyLength = 2048
; Can be 2048, 4096, 8192, or 16384.
; Larger key sizes are more secure, but have
; a greater impact on performance.
Exportable = TRUE
FriendlyName = "Kennethdalbjerg.dk-2024"
MachineKeySet = TRUE
SMIME = False
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
ProviderName = "Microsoft Strong Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0

[EnhancedKeyUsageExtension]

OID=1.3.6.1.5.5.7.3.1 ; this is for Server Authentication

[RequestAttributes]

SAN="kennethdalbjerg.dk&dns=www.kennethdalbjerg.dk"
;-----------------------------------------------

Replace kennethdalbjerg.dk and www.kennethdalbjerg.dk, with the name you want. If you don’t want more than one common name, in yours certificate. Then you just in last line remove:
&dns=www.kennethdalbjerg.dk
Also replace the name in FriendlyName.

Now run this command to prepare the CSR file:

certreq -new certreq.inf certreq.csr

Copy the certreq.csr to yours Certication Authority server, and the run this command on that server

certreq -Submit -Attrib "CertificateTemplate:webserver" -Config - c:\certreq.txt

Replace CertificateTemplate:webserver with the correct name for the template that you want to use.
Save the certificate by name, i use signcert.cer
Copy signcert.cert back to the server, that you have generate the CSR file on, and run this command on that server

certreq -accept signcert.cer

Problems in connection to a Webservice from Windows Server 2016 / 2019

Today, I have this issue, that i could not connect to a webservices, that are hosted by the Danish Tax Service, the URL where: https://emcstest.skat.dk
I got this warning:

Invoke-WebRequest : The request was aborted: Could not create SSL/TLS secure channel.

When running these commands

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$WebResponse = Invoke-WebRequest "https://emcstest.skat.dk"

No matter what I did. But final I tested the webpage against SSLLabs
https://www.ssllabs.com/ssltest/analyze.html?d=emcstest.skat.dk
Found these ciphers

I then run these commands:

Enable-TlsCipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Enable-TlsCipherSuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Enable-TlsCipherSuite TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
Enable-TlsCipherSuite TLS_AES_256_GCM_SHA384
Enable-TlsCipherSuite TLS_AES_128_GCM_SHA256
Enable-TlsCipherSuite TLS_CHACHA20_POLY1305_SHA256
Enable-TlsCipherSuite TLS_AES_256_GCM_SHA384

And finally I where able to access the webpage though powershell.

Problems with FortiClient and no traffic after succesful connection

I have just help a customer, with a problem with his FortiClient.
The Forticlient did connect successful, and everything looks good, but there are no traffic iis recieved.

The OS of the customer where Windows 11.

The solutions where quite simple, just uninstall this microsoft update: KB2693643
Read more about the error here: https://community.fortinet.com/t5/FortiClient/Troubleshooting-Tip-VPN-SSL-connected-but-no-IP-address-in/ta-p/248143

Connect to 365 Exchange mailbox with IMAP and OAuth

Source: https://stackoverflow.com/questions/73370661/php-connect-mailbox-office-365-with-oauth

1 – Configure your mail box in Azure

(I didn’t do this part so i can’t help you more than that ! )

Edit : Thanks to parampal-poonithis link explains how to configurate in azure.

You will need :

  • The client Id
  • The tenant Id
  • The secret client
  • The redirect Uri (Set it to http://localhost/test_imap)

2 – Grab a code to get a token

Construct this url :

$TENANT="5-48...";
$CLIENT_ID="c-9c-....";
$SCOPE="https://outlook.office365.com/IMAP.AccessAsUser.All";
$REDIRECT_URI="http://localhost/test_imap";

$authUri = 'https://login.microsoftonline.com/' . $TENANT
           . '/oauth2/v2.0/authorize?client_id=' . $CLIENT_ID
           . '&scope=' . $SCOPE
           . '&redirect_uri=' . urlencode($REDIRECT_URI)
           . '&response_type=code'
           . '&approval_prompt=auto';

echo($authUri);

Go to the link, connect to the mail box with the passeword. Once it done, you will be redirect to : http://localhost/test_imap?code=LmpxSnTw…&session_state=b5d713….

Save the code (remove the ‘&’ at the end !) and the session state inside the url. These codes expired after a few hours !

When you are on this new page look inside the url, you should have htp:/localhost/test_imap?code=MyCodeIShouldSave&session_state=MySessionIShouldSave This is the $CODE and the $SESSION you are looking for for the step 3

3 – Get an access token

$CLIENT_ID="c-9c-....";
$CLIENT_SECRET="Y~tN...";
$TENANT="5-48...";
$SCOPE="https://outlook.office365.com/IMAP.AccessAsUser.All offline_access";
$CODE="LmpxSnTw...";
$SESSION="b5d713...";
$REDIRECT_URI="http://localhost/test_imap";

echo "Trying to authenticate the session..";

$url= "https://login.microsoftonline.com/$TENANT/oauth2/v2.0/token";

$param_post_curl = [ 
 'client_id'=>$CLIENT_ID,
 'scope'=>$SCOPE,
 'code'=>$CODE,
 'session_state'=>$SESSION,
 'client_secret'=>$CLIENT_SECRET,
 'redirect_uri'=>$REDIRECT_URI,
 'grant_type'=>'authorization_code' ];

$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query($param_post_curl));
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);

$oResult=curl_exec($ch);

echo "result : \n";

var_dump($oResult);

The access_token given in response is going to work only for a few hours. ( If your script is going to be launch on a daily basic you need to recreate a token. I’m going to show you how in the part 5 ! Save the refresh_token inside $oResult. (It are in the middle of the output).
If you don’t have the “refresh_token” you have forgot to put “offline_access” in the scope)

4 – Connect to the mail box

Now choose your favorite library 😉 ! We will use webklex/php-imap for this example (https://github.com/Webklex/php-imap)

include __DIR__.'/vendor/autoload.php'; 
    
use Webklex\PHPIMAP\ClientManager;

$access_token="EH.j8s5z8...";
    
//$cm = new ClientManager($options = ["options" => ["debug" => true]]);                     
$cm = new ClientManager();                      
$client = $cm->make([
    'host'          => 'outlook.office365.com',                
    'port'          => 993,
    'encryption'    => 'ssl',
    'validate_cert' => false,
    'username'      => 'mymailbox@domain.com',
    'password'      => $access_token,
    'protocol'      => 'imap',
    'authentication' => "oauth"
]);

try {
    //Connect to the IMAP Server
    $client->connect();
    $folder = $client->getFolder('INBOX');
    $all_messages = $folder->query()->all()->get();
    //DONE ! :D     
} catch (Exception $e) {
    echo 'Exception : ',  $e->getMessage(), "\n";

5 – Connecting to the mail box everyday

include __DIR__.'/vendor/autoload.php'; 
    
use Webklex\PHPIMAP\ClientManager;

$CLIENT_ID="c-9c-....";
$CLIENT_SECRET="Y~tN...";
$TENANT="5-48...";
$REFRESH_TOKEN="EebH9H8S7...";

$url= "https://login.microsoftonline.com/$TENANT/oauth2/v2.0/token";

$param_post_curl = [ 
 'client_id'=>$CLIENT_ID,
 'client_secret'=>$CLIENT_SECRET,
 'refresh_token'=>$REFRESH_TOKEN,
 'grant_type'=>'refresh_token' ];

$ch=curl_init();

curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query($param_post_curl));
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
//ONLY USE CURLOPT_SSL_VERIFYPEER AT FALSE IF YOU ARE IN LOCALHOST !!!
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);// NOT IN LOCALHOST ? ERASE IT !

$oResult=curl_exec($ch);

echo("Trying to get the token.... \n");

if(!empty($oResult)){
    
    echo("Connecting to the mail box... \n");
    
    //The token is a JSON object
    $array_php_resul = json_decode($oResult,true);
    
    if( isset($array_php_resul["access_token"]) ){

        $access_token = $array_php_resul["access_token"];

        //$cm = new ClientManager($options = ["options" => ["debug" => true]]);                     
        $cm = new ClientManager();                      
        $client = $cm->make([
            'host'          => 'outlook.office365.com',                
            'port'          => 993,
            'encryption'    => 'ssl',
            'validate_cert' => false,
            'username'      => 'mymailbox@domain.com',
            'password'      => $access_token,
            'protocol'      => 'imap',
            'authentication' => "oauth"
        ]);
        
        try {
            //Connect to the IMAP Server
            $client->connect();
        }catch (Exception $e) {
            echo 'Exception : ',  $e->getMessage(), "\n";
        }

    }else{
        echo('Error : '.$array_php_resul["error_description"]); 
    }
}

It will only connect to the mailbox, you then need to write some more code to get access to the mail. Look at https://github.com/Webklex/php-imap

Clear mssql cache

If you for example need to test a query against two SQL servers hardware, its a good idea to clear the cache first.
This query can do this:

DBCC DROPCLEANBUFFERS; 

-- Removes all elements from the plan cache.

DBCC FREEPROCCACHE;

-- Displays the number of milliseconds required to parse, compile, and execute each statement.

SET STATISTICS TIME ON; 

-- Display information regarding the amount of disk activity generated by Transact-SQL statements.

SET STATISTICS IO ON; 

Computer won’t join Azure AD

When going to Settings -> Accounts -> Access work or school, og push the “connect” buttom. I could just see that the popup, asking for my mail address, just popup, but then disapear again very quick.

Starting a powershell with administrative rights, and type in the command

Get-AppXPackage | foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}

And let it run, it toke 1-3 minutes to complete, but when it completed i could push the buttom, and the popup show just fine.

Again this is a danish screenshot.


Veeam backup and Replication – Failed to call RPC function ‘Vss.TruncateSqlLogs’

Today i have this warning in my Veeam Backup and Replication backup job log, for an SQL server:
Failed to finalize guest processing. Details: Failed to call RPC function ‘Vss.TruncateSqlLogs’: Error code: 0x80004005. Failed to invoke func [TruncateSqlLogs]: Unspecified error. Failed to process ‘TruncateSQLLog’ command. Failed to truncate SQL server transaction logs for instances: . See guest helper log.

I found this in the event viewer on the SQL server:
BACKUP failed to complete the command BACKUP LOG [databasename]. Check the backup application log for detailed messages.

So i check the veeam backup log file on the SQL server:
C:\ProgramData\Veeam\Backup
File VeeamGuestHelper_Lastdatefile.log

Where i see this:

19-12-2022 02:08:56 5080 Database found: [databasename]. Recovery model: 1. Is readonly: false. State: 0.
19-12-2022 02:13:56 5080 WARN Cannot truncate SQL logs for database: [databasename]. Code = 0x80040e31
19-12-2022 02:13:56 5080 WARN Code meaning = IDispatch error #3121
19-12-2022 02:13:56 5080 WARN Source = Microsoft OLE DB Driver for SQL Server
19-12-2022 02:13:56 5080 WARN Description = Query timeout expired
19-12-2022 02:13:56 5080 WARN No OLE DB Error Information found: hr = 0x80004005

What i did to fix this error is that i give the user: NT AUTHORITY\SYSTEM the rights db_backupoperator rights to the specific database, that fault.

And also change this timeout value in regedit:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Veeam\Veeam Backup and Replication]
"SqlExecTimeout"=dword:00000600
"SqlLogBackupTimeout"=dword:00003600
"SqlConnectionTimeout"=dword:00000300

And also under WOW6432Node

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\VeeaM\Veeam Backup and Replication]
"SqlLogBackupTimeout"=dword:00003600
"SqlExecTimeout"=dword:00000600
"SqlConnectionTimeout"=dword:00000300

Then try to running the job again.

Expand an EXT4, on a SCSI device

If you have vmware ESXi or Microsoft Hyper-v, you can expand a disk, from the hypervisor console, very simple. But afterwards the partition the servers is not expand.
It is always a good idea to create a Snapshot/checkpoint before. Just remember, that the disc can’t be expanded in Hyper-v when there are a checkpoint. So first expand the disk in Hyper-v and then create a snapshot.

To do this you first need to rescan the disk for change

echo "1" > /sys/class/block/sda/device/rescan

Replace sda with the disk name.
Then you can run fdisk -l /dev/sda, to see the disk information, if you got an error on the top like in the screenshot below

Then you need to repair the disk partition table.

parted -l

After you have check the partition table, you need to delete the old partition, and recreate it

This is done by type fdisk /dev/sda

In the fdisk, you type d to delete, choice the partition, in the example is two. (Beaware that this guide can only be used to expand the last partition on the disk, if you have multiple)
Then you type n to create a new one, and just goes for the default once settings.
In the end type N to not remove the signature.

Then you w to save the settings

Then we just have to resize the ext4 information on the disk, this is done by the command resize2fs

Afterwards you can check that the server have been expand by the command df -h

Here we have expand the disk from 195GB to 295GB.

Get Certificate from remote computers

If you need to get all certificates, from a list of remote computers, you can use this script:

$Servers = "kennethdalbjerg-dc01",
           "kennethdalbjerg-dc02",
           "kennethdalbjerg-exch01",
           "kennethdalbjerg-fs01"
 
  $Results = @()
  $Results = Invoke-Command -cn $Servers {
          $Certs = @{} | Select Certificate,Expired
          $Cert = Get-ChildItem Cert:\LocalMachine\My
          If($Cert){
              $Certs.Certificate = $Cert.subject
              $Certs.Expired = $Cert.NotAfter
          }
          Else{
              $Certs.Certificate = " - "
              $Certs.Expired = " - "
          }
          $Certs
  } | Select-Object @{n='ServerName';e={$_.pscomputername}},Certificate,Expired
 
  #Display results in console
  $Results | Sort-Object Expired -Descending
 
  #Save results to CSV file
  $Results | Sort-Object Expired -Descending | Export-Csv -Path C:\users\$env:username\desktop\cert_results.csv -NoTypeInformation -Force
 
  #Open results in new window
  $Results | Sort-Object Expired -Descending | Out-GridView -Title "Final results"