My Robocopy Command

Quick blurb for my future self when he needs to use Robocopy to copy files from one destination to another quickly.

The below command only copies the data and the attributes but not the permissions. I had some fun issues with copying in the past from a server share so as a result I remove the permissions so I can actually delete or control the directory that I am moving efficiently.

Also, future self, remember that the purge flag is on there and it will kill anything in the destination directory that isn’t in the source.

robocopy "B:/" "C:/DestinationFolder" /W:1 /MT:128 /e /zb /purge /DCOPY:DAT /COPY:DAT /LOG+:myCopyLog.log

Outlook Retention Policy Workaround – VBA Script

Back at it again with the hacky workarounds!

Today I come to you with a VBA Script that I wrote purely out of necessity due to my companies annoying retention policy settings on Outlook.

The Problem:

The Retention Policy is set to 30 Days on our Exchange Inboxes. You may say, “Just change the retention policy” and normally I’d agree, but after speaking with our SysAdmin we are NOT allowed to have that permission on our Inbox or any folders (personally I’d set the policy to keep forever). However, I make extreme usage of the Follow-up feature in Outlook to ensure that I remember to get tasks done or reply to emails. The issue? Sometimes business emails or requests can take longer than 30 days which will cause mail items and task items to be archived and removed from the right sidebar.

See the thing is, Office 365 mailboxes now comes with a “separate” inbox in addition to your primary inbox called “Online Archive”and as a result of some Microsoft wizardry/hard-coding anything that is in this inbox DOES NOT show up on your tasks sidebar in outlook after they are automatically moved due to the retention policy.

The Solution:

The Worst VBA Hack/Macro ever written.

I’ve written a VBA Script that fires on Outlook startup and every 5 hours. It does a “for loop” over every item in the “Online Archive” Inbox, Sent Items, and Tasks folders and moves them to the main inbox.

Below is the code. (Press ALT + F11 to open VBA Editor in Outlook and ensure you have set Outlook to allow VBA Scripts)

To run this properly right click “Modules” and click create new module then paste the below code.

Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerfunc As Long) As Long
Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

Public TimerID As Long 'Need a timer ID to eventually turn off the timer. If the timer ID <> 0 then the timer is running

Public Sub ActivateTimer(ByVal nMinutes As Long)
  nMinutes = nMinutes * 1000 * 60 'The SetTimer call accepts milliseconds, so convert to minutes
  If TimerID <> 0 Then Call DeactivateTimer 'Check to see if timer is running before call to SetTimer
  TimerID = SetTimer(0, 0, nMinutes, AddressOf TriggerTimer)
  If TimerID = 0 Then
    MsgBox "The timer failed to activate."
  End If
End Sub

Public Sub DeactivateTimer()
Dim lSuccess As Long
  lSuccess = KillTimer(0, TimerID)
  If lSuccess = 0 Then
    MsgBox "The timer failed to deactivate."
  Else
    TimerID = 0
  End If
End Sub

Public Sub TriggerTimer(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idevent As Long, ByVal Systime As Long)
  MsgBox "Processing Outlook Items..."
  Call ProcessOutlookItems
End Sub

Sub ProcessOutlookItems()
    Dim objNS As Outlook.NameSpace
    Dim objFolder As Outlook.MAPIFolder
    Set objNS = GetNamespace("MAPI")
    
    Set Archive = objNS.Folders("Online Archive - username@domain.com")
    Set Archive_Inbox = Archive.Folders("Inbox")
    Set Archive_Sent_Items = Archive.Folders("Sent Items")
    Set Archive_Tasks = Archive.Folders("Tasks")
    
    Set Main = objNS.Folders("username@domain.com")
    Set Main_Inbox = Main.Folders("Inbox")
    Set Main_Sent_Items = Main.Folders("Sent Items")
    Set Main_Tasks = Main.Folders("Tasks")
    
    On Error GoTo ErrorHandler
    Dim Msg As Outlook.MailItem

    Call MoveToFolder(Archive_Inbox, Main_Inbox)
    Call MoveToFolder(Archive_Sent_Items, Main_Sent_Items)
    Call MoveToFolder(Archive_Tasks, Main_Tasks)

ProgramExit:
    Exit Sub
ErrorHandler:
    MsgBox Err.Number & " - " & Err.Description
    Resume ProgramExit
End Sub

Sub MoveToFolder(ByVal FolderToParse As Folder, ByVal Destination As Folder)
    
    On Error GoTo ErrorHandler
    
    Dim Msg As Outlook.MailItem
    Dim Task As Outlook.TaskItem
    
    For Each Item In FolderToParse.Items
    
    DoEvents
    
    If TypeName(Item) = "MailItem" Then
        If Item.FlagStatus = olFlagMarked Then
            Item.Move Destination
        End If
    End If
    
    If TypeName(Item) = "TaskItem" Then
        If Item.Status = olFlagMarked Then
            Item.Move Destination
        End If
    End If
    
    Next Item
    
ProgramExit:
    Exit Sub
ErrorHandler:
    MsgBox Err.Number & " - " & Err.Description
    Resume ProgramExit
End Sub

Next, paste the below into “ThisOutlookSession” which will be located on the right sidebar under “Microsoft Outlook Objects”

Private Sub Application_Quit()
  If TimerID <> 0 Then Call DeactivateTimer 'Turn off timer upon quitting **VERY IMPORTANT**
End Sub

Private Sub Application_Startup()
    Call ProcessOutlookItems
    Call ActivateTimer(300) 'Set timer to go off every 1 minute
End Sub

Wew. This was a ton of work for absolutely no reason.

Credit to @niton on StackOverflow for the TriggerTimer Code

Squashing a Docker Image strictly using Bash

Docker images can get big and they sometimes are so large that they become hard to manage. As a result of this you may find yourself needing to decrease this size by removing the layers and that’s where this utility I wrote comes in handy.

Basically what it does is Export the Raw Container File System, Import the Raw File System, Create a new Docker Image from that Raw File System, and Exports/Imports the freshly built Image.

These steps are ELABORATE but unfortunately necessary due to the unfortunate lack of functionality in some of the Docker Squash utilities.

If you find yourself at wits end and have tried all the other Docker Squash tools try the one below I’ve written in Bash.

https://github.com/qwertycody/bash-docker-squash

Setting up RDP Rights on Windows Server 2012 (Non-Administrators)

When working with Windows Server 2012 there are a few ways to grant access to users for Remote Access. If you encounter any issues try these few steps.

  1. Open Windows Explorer -> Right Click This PC -> Properties -> Left Side Bar -> Remote Settings -> “Allow Remote Connections to this Computer”
  2. Open Windows Explorer -> Right Click This PC -> Properties -> Left Side Bar -> Remote Settings -> Select Users -> Add Specified Non-Administrator User
  3. Press Start -> Type “Edit Local Users and Groups” -> Groups (Left Side Bar) -> Remote Desktop Users (Right Click – Properties) -> Add User to Group
  4. (Last Resort, test all others before doing this one) Press Start -> Type “Edit Group Policy” -> Navigate through the Nested Policies to:
    1. Local Computer Policy\Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\Allow log on through Remote Desktop Service
    2. Add User to the Policy Assignment

The above should take care of potential basic issues with Windows Server 2012 and even other versions of Windows such as 7, 8, 8.1, Server 2016, and others.

Start from the top down and test each before moving onto the next with potential reboots in-between each step.

Number 4 should be a last resort.

Docker Sandbox Script – Now with VNC!

Thought I might post a follow-up to my previous post.

As mentioned they lock our computers down at my new company, so I needed a way to test code in a unrestricted environment.

Today, I took it a step further with the addition of a GUI utilizing a VNC Server.

As a bonus I even managed to get RuneScape running on it and it runs suprisingly well, no skips/lag/delay of any kind!

eGLIn5j.png

Below is the source if you’d like to try it out.

@echo off

SET DOCKER="docker"

SET CONTAINER_NAME="linuxSandbox"
SET IMAGE_TO_USE="centos:latest"
SET IMAGE_TO_USE_SANDBOX="sandbox:%CONTAINER_NAME%"

echo Container - %CONTAINER_NAME%
echo Select an Option to Continue:
echo [0] - Container - Create
echo [1] - Container - Start
echo [2] - Container - Stop
echo [3] - Container - Terminal
echo [4] - Container - Destroy

set /p CHOICE="Enter Selection: "

IF "%CHOICE%" == "0" (
%DOCKER% pull "%IMAGE_TO_USE%"

start /MIN "" "%DOCKER%" run -it --privileged --name %CONTAINER_NAME% %IMAGE_TO_USE% bash

timeout 10

%DOCKER% exec -it %CONTAINER_NAME% bash -c "yum -y update;yum clean all"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "yum -y install openssh-server passwd; yum clean all"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "mkdir /var/run/sshd"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "echo 'root:password' | chpasswd"

%DOCKER% exec -it %CONTAINER_NAME% bash -c "yum -y install epel-release"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "yum groupinstall \"Xfce\" -y"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "yum -y install tigervnc-server tigervnc-server-minimal"

%DOCKER% exec -it %CONTAINER_NAME% bash -c "yum -y install file-roller"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "yum -y install java"

%DOCKER% exec -it %CONTAINER_NAME% bash -c "dbus-uuidgen > /var/lib/dbus/machine-id"

%DOCKER% exec -it %CONTAINER_NAME% bash -c "printf \"password\npassword\n\n\" | vncpasswd"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "vncserver -rfbport 5902 "
%DOCKER% exec -it %CONTAINER_NAME% bash -c "vncserver -kill :1"
rem %DOCKER% exec -it %CONTAINER_NAME% bash -c "mv ~/.vnc/xstartup ~/.vnc/xstartup.bekup"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "echo '#!/bin/bash' > ~/.vnc/xstartup"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "echo 'xrdb $HOME/.Xresources' >> ~/.vnc/xstartup"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "echo 'startxfce4 &' >> ~/.vnc/xstartup"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "chmod +x ~/.vnc/xstartup"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "cp /etc/X11/Xresources ~/.Xresources"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "vncserver -rfbport 5902"

%DOCKER% exec -it %CONTAINER_NAME% bash -c "echo 'nohup vncserver -rfbport 5902 &' > /startup.sh"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "echo '/usr/sbin/sshd -D &' >> /startup.sh"
%DOCKER% exec -it %CONTAINER_NAME% bash -c "echo 'ping localhost' >> /startup.sh"
%DOCKER% commit %CONTAINER_NAME% %IMAGE_TO_USE_SANDBOX%
%DOCKER% stop %CONTAINER_NAME%
%DOCKER% rm %CONTAINER_NAME%

%DOCKER% run -d --privileged --name %CONTAINER_NAME% -p "22:22" -p "5902:5902" %IMAGE_TO_USE_SANDBOX% sh /startup.sh
)

IF "%CHOICE%" == "1" (
%DOCKER% start %CONTAINER_NAME%
)

IF "%CHOICE%" == "2" (
%DOCKER% stop %CONTAINER_NAME%
)

IF "%CHOICE%" == "3" (
%DOCKER% exec -it %CONTAINER_NAME% bash
)

IF "%CHOICE%" == "4" (
%DOCKER% stop %CONTAINER_NAME%
%DOCKER% rm %CONTAINER_NAME%
%DOCKER% rmi %IMAGE_TO_USE_SANDBOX%
)

pause

Docker Sandbox Script

Hi all!

It’s been a while since I last posted due to taking the new consulting job but I am back!

Today I was working on a script to allow for ssh into a docker container which would allow that container to effectively be your Sandbox for testing various things.

I personally needed this because at my new job they limit our admin access to the machines but do allow for creation and usage of Docker containers.

You can see where I’m going with this.

Included below is the source if you’d like to try it out.

@echo off

SET %DOCKER%=”docker”

SET CONTAINER_NAME=”linux_sandbox”
SET IMAGE_TO_USE=”centos:latest”
SET IMAGE_TO_USE_SANDBOX=”sandbox:%CONTAINER_NAME%”

echo Container – %CONTAINER_NAME%
echo Select an Option to Continue:
echo [0] – Container – Create
echo [1] – Container – Start
echo [2] – Container – Stop
echo [3] – Container – Terminal
echo [4] – Container – Destroy

set /p CHOICE=”Enter Selection: ”

IF “%CHOICE%” == “0” (
%DOCKER% pull “%IMAGE_TO_USE%”

start /MIN “” “%DOCKER%” run -it –privileged –name %CONTAINER_NAME% %IMAGE_TO_USE% bash

timeout 10

%DOCKER% exec -it %CONTAINER_NAME% bash -c “yum -y update;yum clean all”
%DOCKER% exec -it %CONTAINER_NAME% bash -c “yum -y install openssh-server passwd; yum clean all”
%DOCKER% exec -it %CONTAINER_NAME% bash -c “mkdir /var/run/sshd”
%DOCKER% exec -it %CONTAINER_NAME% bash -c “ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ””
%DOCKER% exec -it %CONTAINER_NAME% bash -c “echo ‘root:password’ | chpasswd”

%DOCKER% commit %CONTAINER_NAME% %IMAGE_TO_USE_SANDBOX%
%DOCKER% stop %CONTAINER_NAME%
%DOCKER% rm %CONTAINER_NAME%

%DOCKER% run -d –privileged –name %CONTAINER_NAME% -p “22:22” %IMAGE_TO_USE_SANDBOX% /usr/sbin/sshd -D
)

IF “%CHOICE%” == “1” (
%DOCKER% start %CONTAINER_NAME%
)

IF “%CHOICE%” == “2” (
%DOCKER% stop %CONTAINER_NAME%
)

IF “%CHOICE%” == “3” (
%DOCKER% exec -it %CONTAINER_NAME% /bin/bash
)

IF “%CHOICE%” == “4” (
%DOCKER% stop %CONTAINER_NAME%
%DOCKER% rm %CONTAINER_NAME%
%DOCKER% rmi %IMAGE_TO_USE_SANDBOX%
)

pause

 

Manually Validating a Self-Signed Cert in C-Sharp

I’ve been working a lot in Docker containers in the past couple of weeks and I came across the obstacle where a self signed cert was causing issues because the Docker container did not recognize the Certificate Authority.

After a good bit of research, I came up with a solution that manually validates the cert based off building the chain and verification of the thumbprint.

Note: You have to be using a library that supports a Certificate Validation Callback so that you can code your own delegate method. Below is my implementation.

public static bool ManualSslVerification(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
try
{
//Testing to see if the Certificate and Chain build properly, aka no forgery.
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.Build(new X509Certificate2(certificate));

//Looking to see if there are no errors in the build that we don’t like
foreach (X509ChainStatus status in chain.ChainStatus)
{
if (status.Status == X509ChainStatusFlags.NoError || status.Status == X509ChainStatusFlags.UntrustedRoot)
{
//Acceptable Status, We want to know if it builds properly.
}
else
{
return false;
}
}

X509Certificate2 trustedRootCertificateAuthority = new X509Certificate2(ViewController.Properties.Resources.My_Infrastructure_Root_CA);

//Now that we have tested to see if the cert builds properly, we now will check if the thumbprint of the root ca matches our trusted one
if(chain.ChainElements[chain.ChainElements.Count – 1].Certificate.Thumbprint != trustedRootCertificateAuthority.Thumbprint)
{
return false;
}

//Once we have verified the thumbprint the last fun check we can do is to build the chain and then see if the remote cert builds properly with it
//Testing to see if the Certificate and Chain build properly, aka no forgery.
X509Chain trustedChain = new X509Chain();
trustedChain.ChainPolicy.ExtraStore.Add(trustedRootCertificateAuthority);
trustedChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
trustedChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
trustedChain.Build(new X509Certificate2(certificate));

//Looking to see if there are no errors in the build that we don’t like
foreach (X509ChainStatus status in trustedChain.ChainStatus)
{
if(status.Status == X509ChainStatusFlags.NoError || status.Status == X509ChainStatusFlags.UntrustedRoot)
{
//Acceptable Status, We want to know if it builds properly.
}
else
{
return false;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
return false;
}

return true;
}
}