Showing posts with label work. Show all posts
Showing posts with label work. Show all posts

Wednesday, May 18, 2016

Visual Studio POSH snippet, DocuComment

I am trying to get into more Visual Studio (as that is what "real" programmers use).... and to my delight, I found out that PowerShell is more supported than ever before in VS 2015.  Perhaps I can finally put away my childish things (ISE) and move onto something much more unnecessarily complicated.   So when I read about "code snippets" I was excited... but....

 No matter how much I searched, I could not find one for a simple "documentation block."  You know, the one with the ".Synopsis", and ".Example" that we are supposed to use in our scripts, but never do?  Perhaps I can make the world a better place by figuring it out and allowing others to use it.  Now you have no excuse to not document your code better, you are just three clicks away from having the "DocuComment" block created for you!

You will need to put the code below in to a file with an extension of ".snippet" and import it into VS.
(Details of this can be found at: https://msdn.microsoft.com/en-us/library/9ybhaktf(v=vs.100).aspx )

DocuComment.snippet :

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>DocuComment Block</Title>
      <Shortcut>docucomment</Shortcut>
      <Description>Code snippet for a comment block.</Description>
      <Author>Bryan Loveless bryan.loveless@gmail.com</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
        <SnippetType>SurroundsWithStatement</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>param1</ID>
          <ToolTip>DocuComment</ToolTip>
          <Default>
            .SYNOPSIS

            synopsis of script, overall idea



            .DESCRIPTION

            description of overall script, more detail than synopsis



            .PARAMETER parameternamehere

            parameter description, if required, possible values



            .PARAMETER path

            parameter path



            .EXAMPLE

            example of script use, return behavior.



            .EXAMPLE

            another exmample if there are more.  This can be repeated for as many examples as you want



            .NOTES

            other misc notes, perhaps permissions needed, dates of script.
          </Default>
        </Literal>
      </Declarations>
      <References />
      <Code Language="PowerShell">
        <![CDATA[<#
$param1$
$selected$ $end$
#>]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

Wednesday, December 16, 2015

The Netscaler is hiding stuff from you...

I have been thinking recently about how to hid my infrastructure info from the public, and one easy way is to stop telling the world what type of webserver you are running.  Now I am not going to get into the discussion of whether or not "security through obscurity" works... but this is so easy, even if it hinders some script kiddies, I will be happy.

There are lots of ways to see the response headers from your webserver, and I found a scanner that will tell you that and a bit more:  https://securityheaders.io I ran some of my URLs though the device, and sure enough, they are blabbing to the world what versions of whatever it has.... 

So instead of trying to figure out how to get all of my webservers to shut up, I decided to use the Netscaler to just remove the headers before they are presented to the client.  I must admit, it was pretty easy... from the CLI.  When I tried it from the GUI, I had a strange message and didn't want to fuss around with it much more.

 -----------------------------

Remove "Server" header:

add rewrite action Delete_server_header_action delete_http_header Server -bypassSafetyCheck YES -comment "This will delete the Server Header field from Server's response before sending to client"

add rewrite policy Delete_server_header_policy "HTTP.RES.HEADER(\"Server\").EXISTS" Delete_server_header_action -comment "This will delete the Server header field from server\'s response before sending to client"

Now to remove "x-powered-by" header:

add rewrite action Delete_x-powered-by_header_action delete_http_header X-Powered-By -comment "This will delete the X-Powered-By Header field from Server's response before sending to client"

add rewrite policy Delete_x-powered-by_header_policy "HTTP.RES.HEADER(\"X-Powered-By\").EXISTS" Delete_x-powered-by_header_action -comment "This will delete the X-Powered-By header field from server\'s response before sending to client"

-------------------------

then bind them both to your Content Switching Virtual Server, give it priority of 85 (in my case I had a few others I want to run afterwards), and change "goto expression" to "NEXT"


Easy, right?  Now run your test again, and those headers are now missing... of course, you could replace the headers with something fun, like "X-Powered-By: The Dark Side" or whatever.... but I am not sure my employer would appreciate the humor as much as I would.

Tuesday, August 4, 2015

Netscaler cert... damn thing hung up on me again

Netscaler has a strange GUI that I think was designed as an "afterthought" by the developers.  The more you use it, the more you try to figure out why stuff is in the order it is, or the grouping it is in.  Sometimes the Netscaler will perform an operation, and drop your connection without warning.  So here is how to install Certificates, which might end in a dropped connection when associating a cert to the device management interface.

Request a certificate as you would normally do, using IIS.  This has been documented plenty of other places, so skipped here. 

Because of the HA pair, you will need one cert, but make it good for 2 DNS names, including NS.blah.com and NS-Otherlocation.blah.com

This is also good for moving a site's SSL certificate to the Netscaler for load balancing from an IIS host.

Visit http://www.derekseaman.com/2013/05/import-iis-ssl-certificate-to-citrix-netscaler.html on how to export this new certificate into the Netscaler UNTIL the section where you have to upload it to the NETSCALER
(Mr Derek Seaman's instructions are good, but not for our NS version.  You can probably figure it out with clicking around, but just in case:)
 At this point, on the Netscaler, you select Traffic management --> ssl and "import PKCS#12"
Most of Mr Seaman's instructions will still work, but things may be very slightly out of order, like the order to click "browse" or whatever... but it is much easier with his diagrams than I can explain here.  Remember to use a good password manager to generate and store any passwords you use in this process.
When you are finished, the cert is ready to be used with your VIP.

IF YOU ARE INSTALLING THE CERT FOR THE NETSCALER DEVICE ITSELF:
Skip the step above where you upload the certificate, or remove it from the Netscaler if you have already uploaded it.

Download the "X509 Certificate only, Base64 encoded" file and open it in a text editor.
blah_com_cert.cer

Download the "X509 Intermediates/root only Reverse, Base64 encoded: " file and open it as well.
blah_com_interm.cer

Create a new text file.  Copy the X509 Certificate only, Base64 encoded  cert to it first and then copy the NEXT two X509 Intermediates/root only Reverse, Base64 encoded certs from the file below the first. (They will be the first two in the blah_com_interm.cer file. The root is the last one in that file and you don't want it.) Now save the file with a meaningful name, like "blah_com-bun-noroot.crt".  (bun=bundle)

Login into the NS and upload your cert bundle and private key. In this example they would be blah_com.key and blah_com-bun-noroot.crt.
Then under SSL/Certificates select the ns-server-certificate and update it. There's a check box on the Update Certificate window that says, Click to update Certificate/Key. Select that and then browse for the two files you just uploaded.  Also check the box "no domain check" if you are switching domain suffixes . 
 After clicking "ok", wait a min or two... then you will have to reconnect your browser.
Check the certificate in the browser, it should list new certificate.
 
You do not have to modify the other Node in the HA pair, the HA standby member gets updated automatically.

You can diagnose/view the certs you uploaded using "shell" and "openssl x509 -in NAMEOFFILE.cer -text -noout"

Happy balancing,
-_Bryan

Friday, July 31, 2015

Splunkin' the Windows Firewall Log automagically

Splunk and Windows Firewall logging, gettin' the fields out.

I spent a a bit of time trying to figure out how to get SPLUNK to parse out our Window Firewall logs.  I found several sites explaining how it should work.
I was able to get Transforms working by using the site http://answers.splunk.com/answers/107278/windows-firewall-log-extraction-transforms.html .

For example, after feeding the logs into Splunk with a simple file monitor and forwarder, I would enter: " sourcetype=pfirewall | extract Transform_Windows_FW " and it would parse out the fields.


 I wanted this to happen automagically, so I tried the second part of the link above, where you edit the props.conf file.... fail.  So long story short, I edited the props.conf file to contain:
"

[pfirewall]
EXTRACT-date,time,action,protocol,src_ip,dst_ip,src_port,dst_port,size,info = ^(?P<date>[^ ]+)\s+(?P<time>[^ ]+)\s+(?P<action>[^ ]+)\s+(?P<protocol>\w+)[^ \n]* (?P<src_ip>[^ ]+)\s+(?P<dst_ip>[^ ]+)\s+(?P<src_port>[^ ]+)\s+(?P<dst_port>[^ ]+)\s+(?P<size>[^ ]+)(?:[^ \n]* ){8}(?P<info>\w+)


"
and added it to my search head.  Tested with IPv6 and it seems to work fine.
(Technically a co-worker tried this as I was trying other things, so he gets the credit)


p.s. You must edit the C:\Program Files\Splunk\etc\system\local\props.conf file, not the one in the default folder, or you might mess up some default functionality of Splunk.


Tuesday, July 21, 2015

Netscaler N00b no more?

My employer purchased a few Netscalers (NS) and put me and another dozen or so folks through training on how to configure and use it. But, nothing prepared me for the strange way Citrix and Citrix-fans write their documentation.

So here are a few things I learned in the last few weeks working with it:

 1) AD and AAA - there are many articles on how to use AAA with Active Directory. (http://support.citrix.com/article/CTX111079 for example)  I searched for quite some time trying to figure out how to "link" an AD group to a NS group.  I assumed I would have to create a group on the NS, then tell the NS to associate that group with the AD group.... But no.  I wanted to customize what the NS group was called, but you cannot.  So here was my trick:  Create a group on the NS EXACTLY the way it is spelled in AD and associate it with a policy ( I used a built-in NS policy).  Then under "System, authentication, LDAP, Servers tab, the value I used was:
 "memberOf=CN=ad_group_name_here,OU=ou_where_group_is_located,DC=domain_name,DC=dopmain_name,DC=domain_name,DC=com" .  In short, a NS local group of the same name is associated with a local LDAP policy which is searched for using location in AD.
Also, here is another thing that I hope will save you some time.  LDAP using FQDNs did not work for us.  Instead, I had to create one server LDAP policy for each of our domain controllers using their individual IPs.  DNS is setup, and seems to work great with everything else tested (ping, traceroute), but it appears the Nestcaler does not handle multiple A record responses from a DNS server in this circumstance.

2) AppExpert Templates - I was experimenting with SharePoint behind the NS, and I came across the AppExpert Template for it.     It looked pretty neat, with lots of optimizations and promises of improved performance. 

I tried using many walk-troughs to implement it, but none of them seemed to work:
https://www.citrix.com/content/dam/citrix/en_us/documents/products-solutions/microsoft-sharepoint-2013-with-citrix-netscaler.pdf
https://www.paloaltonetworks.com/content/dam/paloaltonetworks-com/en_US/assets/pdf/technology-solutions-briefs/citrix/panw-netscaler-sharepoint.pdf
https://www.citrix.com/content/dam/citrix/en_us/documents/products-solutions/citrix-netscaler-datasheet-microsoft-sharepoint-2013.pdf

So, here is what I had to know to get the template properly installed:
-- The NAME you first enter MUST NOT include any special characters.  It will error towards the end with a strange message if you do.
-- You must not already have the resource of the "public endpoint" as a current Load balanced server or anywhere else if you can help it. The only thing you should have configured is the VIP configured on the NS itself.   The template will create the server for you.
--  Only a N00b like me probably thought this, but the template does not create a "load balanced" server, it created a "content switching server."  
-- If you need to delete the template, you will have to remove all of the Response, Rewrite, and all the other Policies and Actions it creates.  Luckily they will start with the name you provided above.

3) Mac address filtering -  We have some "real servers" and some VIPs behind and in front of the NS.  We could not figure out why the traffic would disappear.  It turned out that you must enable "
MAC based forwarding" under System, Settings, Configure Modes.  The networking team here hated me for a few days, and they thought I was an idiot, as their NS instance worked fine... but they didn't have anything that had to traverse a firewall.  This little checkbox was the reason it only half-worked for me.

4) Routes -  For me, the GUI is really confusing, as they have a column that says "Gateway/Owned IP/Name."  Long story short, add Routes using the CLI as it makes a hell of a lot more sense.

May your life and servers be forever balanced,
-_Bryan

Tuesday, June 23, 2015

Simply log what VM is running and where.

We have an issue where randomly a node in our Hyper-V cluster will fail.  We know it is related to an iSCSI event, but we cannot reproduce the error.  Since we don't know what is running when it happens, I thought we could simply log what VMs are running, and on what hosts.
I looked around the internets (or BinGled so to speak) and didn't see anyone who was simply listing the Hyper-V virtual machines running on a host. (Some folks were doing it for Citrix for VMware, but not Hyper-V.)
So I wrote a simple script that will display it on the screen, along with writing it to a file (as we plan on running this script every 24 hours or so, waiting for a crash).



####################################################################################
####################################################################################

<#.Synopsis 
    List all VMs running in the cluster, along with what host it is running on and writes them to a location of your choosing.

.Description 
     List all VMs running in the cluster, along with what host it is running on and writes them to a location of your choosing.

.Parameter  filetowrite
            Path and file name to write the output to.
    

.Parameter clustergroupname
            Cluster name itself, Fully qualified recommended
         

.Example 
    .\List-Vms -filetowrite c:\temp\vmlist.txt -clustergroupname YOURCLUSTERNAMEHERE-FQDN

.Notes 
  Author: Bryan Loveless bryan.loveless@gmail.com
  Requires -Version 4.0 
   
 Version: 1.0
 Updated: 22.June.2015
   LEGAL: PUBLIC DOMAIN.  SCRIPT PROVIDED "AS IS" WITH NO WARRANTIES OR GUARANTEES OF 
          ANY KIND, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY AND/OR FITNESS FOR
          A PARTICULAR PURPOSE.  ALL RISKS OF DAMAGE REMAINS WITH THE USER, EVEN IF
          THE AUTHOR, SUPPLIER OR DISTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF
          ANY SUCH DAMAGE.  IF YOUR STATE DOES NOT PERMIT THE COMPLETE LIMITATION OF
          LIABILITY, THEN DELETE THIS FILE SINCE YOU ARE NOW PROHIBITED TO HAVE IT.

#>

Function List-VMs
{
[CmdletBinding()]
    Param (
        [Parameter(
            Position=1,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true,
            #ValidateNotNullOrEmpty(),
            Mandatory=$true,
            HelpMessage="Filepath and name?"
            )
         ]
           [string]$filetowrite = ("c:\temp\VMlist.txt"),
       

        [Parameter(
            Position=2,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true,
            #ValidateNotNullOrEmpty(),
            Mandatory=$true,
            HelpMessage="What is the name of the cluster?"
            )
         ]
            [string]$clustergroupname = ("YOURCLUSERNAMEHERE-FQDN")
     )  


    get-date | out-file $filetowrite -Append
    $OutArray = @()

    $clusterNodes = Get-ClusterNode -cluster $clustergroupname;
        ForEach($item in $clusterNodes)
            {
            write-host "RUNNING ON " ($item.name).ToString() ":" -foregroundcolor GREEN
            $item | out-file $filetowrite -Append
       
            $vms = Get-VM -ComputerName $item.Name
                ForEach($vm in $vms)
                {
                    write-host $vm.Name $vm.State "CPU used:" $vm.cpuusage "%" "Uptime:" $vm.uptime $vm.Status
                    $vm | Format-table name, state, cpuusage, memoryassigned, uptime, status | out-file $filetowrite -Append
                 }
                
            } 

}



#now to run it
List-VMs -filetowrite c:\temp\vmlist.txt -clustergroupname YOURCLUSTERNAMEHERE-FQDN

# FIN

Wednesday, April 22, 2015

Confuse your Local Admin, repeatedly. Part 2 - decrypt

Here we decrypt the password, using the private key stored in the local cert or user cert store.

####################################################################################
#.Synopsis 
# Retrieve attribute from AD using powershell
#
#.Description 
#  Retrieve attribute from AD using powershell
#
#
#.Parameter ComputerNames
#   One or more computer names that you are requesting the password for.
#
#.Example 
# ./Get-EncryptedPasswordFromCarLicenseInAD.ps1 -computer machine1
# This will return the password for the listed machine.
#
#.Example 
# ./Get-EncryptedPasswordFromCarLicenseInAD.ps1 -computernames machine1,machine2
# This will return the passwords for both machines listed
#
#
#Requires -Version 3.0 
#
#.Notes 
#  Author: Bryan Loveless bryan.loveless@gmail.com
# 
# Version: 1.0
# Updated: 17.April.2015
#   LEGAL: PUBLIC DOMAIN.  SCRIPT PROVIDED "AS IS" WITH NO WARRANTIES OR GUARANTEES OF 
#          ANY KIND, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY AND/OR FITNESS FOR
#          A PARTICULAR PURPOSE.  ALL RISKS OF DAMAGE REMAINS WITH THE USER, EVEN IF
#          THE AUTHOR, SUPPLIER OR DISTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF
#          ANY SUCH DAMAGE.  IF YOUR STATE DOES NOT PERMIT THE COMPLETE LIMITATION OF
#          LIABILITY, THEN DELETE THIS FILE SINCE YOU ARE NOW PROHIBITED TO HAVE IT.
####################################################################################

# Get-EncryptedPasswordFromCarLicenseInAD.ps1


[CmdletBinding()]
Param (  
        [Parameter(
            Position=0,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$True,
   Mandatory=$false,
            HelpMessage="What is/are the computer names?"
            )
         ]
           [string[]]$ComputerNames = ("machine1","machine2") #change back to "$env:computername" to run on local machine
     )    

####################################################################################
# Decrypts TXT using public key
# Decrypt-Asymmetric -EncryptedBase64String $Base64String -CertThumbprint "‎thumbprintHere" 
####################################################################################
Function Decrypt-Asymmetric
{
    [CmdletBinding()]
    [OutputType([System.String])]
    param(
        [Parameter(Position=0, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
        $EncryptedBase64String,
        [Parameter(Position=1, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
        $CertThumbprint
    )
    # Decrypts cipher text using the private key
    # Assumes the certificate is in the LocalMachine\My (Personal) Store
    
 #below looks in local computer store for cert
 #$Cert = Get-ChildItem cert:\LocalMachine\My | where { $_.Thumbprint -eq $CertThumbprint }
 
 # below looks in current user store for cert
 #$Cert = Get-ChildItem cert:\CurrentUser\my  | where { $_.Thumbprint -eq $CertThumbprint }
 
 # below looks in the current user's certificates and private keys AND CHECKS THEM.
  # reference: Jason Fossen, Enclave Consulting (http://cyber-defense.sans.org/blog
 try
 {
     $readonlyflag = [System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly
     $currentuser =  [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
     $usercertstore = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $currentuser
     $usercertstore.Open($readonlyflag) 
     $usercertificates = $usercertstore.Certificates
 }
 catch
 {
     "`nERROR: Could not open your certificates store. `n"
     exit
 }
 finally
 {
     $usercertstore.Close() 
 }

 if ($usercertificates.count -eq 0) { "`nERROR: You have no certificates or private keys.`n" ; exit }
  
# Load the correct certificate and test for possession of private key.
    $cert = $usercertificates | where { $_.thumbprint -eq $CertThumbprint } 
    if (-not $cert.hasprivatekey) 
    { 
        $output.StatusMessage = "ERROR: You do not have the private key for this certificate."
        $output.Valid = $false
        $output
        continue
    }
 
    if($Cert) {
        $EncryptedByteArray = [Convert]::FromBase64String($EncryptedBase64String)
        $ClearText = [System.Text.Encoding]::UTF8.GetString($Cert.PrivateKey.Decrypt($EncryptedByteArray,$true))
    }
    Else {Write-Error "Certificate with thumbprint: $CertThumbprint not found!"}
 
    Return $ClearText
  #reference: http://jeffmurr.com/blog/?p=228
}

#Create the array to store all decrypted passwords
$AllPasswords = @()

ForEach ($ComputerName in $ComputerNames){
# retrieve where the machine lives in AD 
 $Filter = "(&(objectCategory=Computer)(Name=$ComputerName))"
 $DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
 $DirectorySearcher.Filter = $Filter
 $SearcherPath = $DirectorySearcher.FindOne()
 $machine = $SearcherPath.GetDirectoryEntry()

#get the "carLicense" attribute from AD
 $carLicenseAttribute = ($machine.carLicense)
  
# get thumbprint of the certificate, create object for it, then set thumbprint for comparison
 $output = ($output = " " | select-object Valid,StatusMessage,Password,Thumbprint)
    $output.Valid =        $false  #Assume password recovery will fail.
 #
 $output.Thumbprint = "‎PUTYOURCERTIFICATETHUMBPRINTHEREOFTHEONEYOUEXPECT"

# Load the current user's certificates and private keys.
 try
 {
     $readonlyflag = [System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly
     $currentuser =  [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
     $usercertstore = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $currentuser
     $usercertstore.Open($readonlyflag) 
     $usercertificates = $usercertstore.Certificates
 }
 catch
 {
     "`nERROR: Could not open your certificates store. `n"
     exit
 }
 finally
 {
     $usercertstore.Close() 
 }

 if ($usercertificates.count -eq 0) { "`nERROR: You have no certificates or private keys.`n" ; exit }
  
# Load the correct certificate and test for possession of private key.
    $thecert = $usercertificates | where { $_.thumbprint -eq $output.thumbprint } 
    if (-not $thecert.hasprivatekey) 
    { 
        $output.StatusMessage = "ERROR: You do not have the private key for this certificate."
        $output.Valid = $false
        $output
        continue
    } 
    

# Test to confirm that the private key can be accessed, not just that it exists.  The
# problem is that it is not a trivial task to allow .NET or PowerShell to use
# private keys managed by Crytography Next Generation (CNG) key storage providers, hence,
# these scripts are only compatible with the older Cryptographic Service Providers (CSPs), such
# as the "Microsoft Enhanced Cryptographic Provider", but not the newer CNG "Microsoft
# Software Key Storage Provider".  Sorry...
    if ($thecert.privatekey -eq $null) 
    { 
        $output.StatusMessage = "ERROR: This script is not compatible with CNG key storage providers."
        $output.Valid = $false
        $output
        continue
    } 


#Remove Date information, Decrypt password using private key, and return vaule
$decryptedPassword = Decrypt-Asymmetric -EncryptedBase64String (($carLicenseAttribute.ToString()).SubString(19)) -CertThumbprint $output.Thumbprint
Write-Host $computername"'s" "password is" $decryptedPassword

$AllPasswords= $allpasswords + ($decryptedPassword)

Remove-Variable decryptedPassword
}

#returns all of the passwords in the array together, in case script was called expecting returns
Write-Host "Here are all of the passwords you requested:"
Return $AllPasswords
Remove-Variable AllPasswords

# FIN

Confuse your Local Admin, repeatedly. Part 1 - change and encrypt

We recently found out that some of our departmental desktop admin staff have been forgetting to change the password for the LocalAdmin account after imaging a machine. Our Information Security team found out this was so widespread, they asked my team to solve this issue. Politics aside, here is what we decided on:
 1) Change Local Admin username to something else.
2) Change this new user's password to something unique between every device.
 3) Encrypt this password using a public key, then store it in Active Directory.
4) Be able to control who can receive and decrypt this password, and how.
5) Be able to change this password as often as we want, by only issuing a new GPO.
6) Set how often to change the password, as every time it starts seems to harsh.

And now the solutions/background of solutions:
 1) Bing how to change local admin username using GPOs. It is super easy.
 2) Most password generators I found on the internet rely on Powershell's "Get-Random"... that is not truly random. It is based upon system up-time, so someone much smarter than me might be able to figure out the random seed. So I had help from a buddy at work, and we wrote another get-randompassword function that bases passwords on the .NET security provider. (see code)
3) With the borrowed code from the internet, I discovered this is much easier than I thought it would be. So I generate a "really strong" self-signed cert that is good for 10 years (because we had to take into account a machine that was taken off the domain, and how to access the data on it after it has been purged from AD). I put the public cert in the domain's NETLOGON area, so every authenticated object is able to access it. The private key is (obviously) stored somewhere else, very, very protected. Also, this enables us to flip out the public cert if we need to someday.
4) We are still discussing this, but I will post the code to decrypt the info in "Part 2". The code right now will work if the user logged in or the machine have a certificate that matches the public key, but the idea of a webpage has been discussed allowing our desktop admins to authenticate to a webpage and never have access to the private key itself.
 5) With one digit in the POSH, easy-cheesy.
6)  I write the value of the last time the password was changed in the AD attribute, then, if over a certain amount of days, I change it again.  This prevents us from having the user who "will get around to migrating to the new machine" but doesn't do it within a week or two.  Again, this is set in the code, very easy to change.

 Now of course, I need to mention I am just a simple Sysadmin, so if this breaks your stuff, then don't blame me... you should have consulted a programmer.

####################################################################################
#.Synopsis 
#    Resets the password of a local user account with a random password which is 
#    then encrypted with your pubic key certificate and stored in AD attribute under
#  the computer object. The plaintext password is 
#    displayed with the  Get-EncryptedPasswordFromCarLicenseInAD.ps1 
#  script. 
#
#.Description 
#    Resets the password of a local user account with a 16-25 character, random, 
#    complex password, which is encrypted with your own pubic key certificate and then
#  stored under an Active Directory Attribute for the computer object. 
#    Recovery of the encrypted password from Active Directory requires possession of the
#    private key corresponding to the chosen public key certificate.  The password
#    is never transmitted or stored in plaintext. The plaintext password 
#    is recovered with the companion 
#  Get-EncryptedPasswordFromCarLicenseInAD.ps1 script.  The
#    script must be run with administrative or local System privileges. 
#  The Private Key for decryption may be stored in either the Computer's Cert Store or the
#  User's cert store.
#
#.Parameter CertificateFilePath 
#    The local or UNC path to the .CER file containing the public key 
#    certificate which will be used to encrypt the password.  The .CER
#    file can be DER- or Base64-encoded.  (But note that the private
#    key for the certificate cannot be managed by a Cryptography Next
#    Generation (CNG) key storage provider, hence, do not use the Microsoft 
#    Software Key Storage Provider in the template for the certificate.)
#
#.Parameter LocalUserName
#    Name of the local user account on the computer where this script is run
#    whose password should be reset to a 16-25 character, complex, random password.
#    Do not include a "\" or "@" character, only local accounts are supported.
#    Defaults to "Guest", but any name can be specified.
#
#
#.Parameter MinimumPasswordLength
#    The minimum length of the random password.  Default is 16.  The exact length
#    used is randomly chosen to increase the workload of an attacker who can see
#    the contents of this script.  Maximum password length defaults to 25.  The
#    smallest acceptable minimum length is 4 due to complexity requirements.
#
#.Parameter MaximumPasswordLength
#    The maximum length of the random password.  Default is 16.  Max is 127.
#    The minimum and maximum values can be identical.    
#
#.Example 
#    .\Set-EcryptedPasswordToCarLicenseInAD.ps1 -CertificateFilePath \\server\share\certificate.cer 
#
#    Resets the password of the default account, encrypts that password 
#    with the public key in the certificate.cer file, and saves the encrypted
#    password in the AD attribute "carLicense".  Choose a different account with -LocalUserName.
#
#
#.Example 
#    .\Set-EcryptedPasswordToCarLicenseInAD.ps1 -LocalUserName HelpDeskUser -CertificateFilePath \\server\share\certificate.cer
#
#    The local account's password is reset by default, but any
#    local user name can be specified instead.
#
#
#Requires -Version 2.0 
#
#.Notes 
#  Author: Bryan Loveless bryan.loveless@gmail.com, based upon script by
#   Jason Fossen, Enclave Consulting (http://cyber-defense.sans.org/blog)
#   Password cryptographic method by Bryan Loveless bryan.loveless@gmail.com
# Version: 1.0
# Updated: 17.April.2015
#   LEGAL: PUBLIC DOMAIN.  SCRIPT PROVIDED "AS IS" WITH NO WARRANTIES OR GUARANTEES OF 
#          ANY KIND, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY AND/OR FITNESS FOR
#          A PARTICULAR PURPOSE.  ALL RISKS OF DAMAGE REMAINS WITH THE USER, EVEN IF
#          THE AUTHOR, SUPPLIER OR DISTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF
#          ANY SUCH DAMAGE.  IF YOUR STATE DOES NOT PERMIT THE COMPLETE LIMITATION OF
#          LIABILITY, THEN DELETE THIS FILE SINCE YOU ARE NOW PROHIBITED TO HAVE IT.
####################################################################################

# Set-EncryptedPasswordToCarLicenseInAD.ps1

Param ($CertificateFilePath = ".\LocalAdminPasswordChangePublicCert.cer", $LocalUserName = "bryan", $MinimumPasswordLength = 16, $MaximumPasswordLength = 25) 



####################################################################################
# Below replaces the generate-randompassword used on a previous version of this script,
#   as the older one used get-random and this new one uses the .net cryptographic provider
#####################################################################################
function Generate-Password() {


param( 
[int] $len = 16,
[string] $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_!@#$%^&*()_"
)

$result = ""
for( $i=0; $i -lt $len; $i++ )
{
  

$bytes = new-object "System.Byte[]" 1
$rnd = new-object System.Security.Cryptography.RNGCryptoServiceProvider
$rnd.GetBytes($bytes)



    if ($bytes[0] -gt (([int](256/$chars.Length))*$chars.length))
        { 
            $i-- 
            continue
        }

$result += $chars[ $bytes[0] % $chars.Length ] 
}


return $result

  <#
    .SYNOPSIS 
        Returns a secure password, based on the System's Crytpo Service Provider.

    .EXAMPLE
     Generate-Password 
        Returns a  16 character password, using A-Z, numbers, and the "easier to type" special characters

    .EXAMPLE
     Generate-Password -len 48 -chars "0123456789"
        Returns a 48 length numeric password

    .EXAMPLE
    Generate-Password -len 1 -chars "01" 
        Returns a one character password that is either a 0 or a 1"


    .NOTES
        Modified by Bryan Loveless    bryan.loveless@gmail.com Jan 2015
        Based on http://www.peterprovost.org/blog/2007/06/22/Quick-n-Dirty-PowerShell-Password-Generator/
        BUT modified to be a little bit more secure

  #>
}

####################################################################################
# Returns true if password reset accepted, false if there is an error.
# Only works on local computer, but can be modified to work remotely too.
####################################################################################
Function Reset-LocalUserPassword ($UserName, $NewPassword)
{
    Try 
    {
        $ADSI = [ADSI]("WinNT://" + $env:ComputerName + ",computer")
        $User = $ADSI.PSbase.Children.Find($UserName)
        $User.PSbase.Invoke("SetPassword",$NewPassword)
        $User.PSbase.CommitChanges()
        $User = $null 
        $ADSI = $null
        $True
    }
    Catch
    { $False } 
}

####################################################################################
# Writes to console, writes to Application event log, optionally exits.
# Event log: Application, Source: "PasswordArchive", Event ID: 9013
####################################################################################
function Write-StatusLog ( $Message, [Switch] $Exit )
{
    # Define the Source attribute for when this script writes to the Application event log.
    New-EventLog -LogName Application -Source PasswordArchive -ErrorAction SilentlyContinue

    "`n" + $Message + "`n"

#The following here-string is written to the Application log only when there is an error, 
#but it contains information that could be useful to an attacker with access to the log.
#The data is written for troubleshooting purposes, but feel free change it if concerned.
#It does not contain any passwords of course.
$ErrorOnlyLogMessage = @"
$Message 

CurrentPrincipal = $($CurrentPrincipal.Identity.Name)

CertificateFilePath = $CertificateFilePath 

LocalUserName = $LocalUserName

PasswordArchivePath = $PasswordArchivePath

ArchiveFileName = $filename
"@

    if ($Exit)
    { write-eventlog -logname Application -source PasswordArchive -eventID 9013 -message $ErrorOnlyLogMessage -EntryType Error }
    else
    { write-eventlog -logname Application -source PasswordArchive -eventID 9013 -message $Message -EntryType Information }

    if ($Exit) { exit } 
}

####################################################################################
# Writes to AD attribute
# 
####################################################################################
Function SendAttribute-ToAD
{
[CmdletBinding()]
    Param (
        [Parameter(
            Position=1,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true,
            #ValidateNotNullOrEmpty(),
            HelpMessage="What is the field name that you would like to edit?"
            )
         ]
           [string]$PropertyToEdit,
       

        [Parameter(
            Position=2,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true,
            #ValidateNotNullOrEmpty(),
            Mandatory=$true,
            HelpMessage="What do you want the new entry to be?"
            )
         ]
            [string]$EditedInfo
     )    

$ComputerName = $env:computername
$Filter = "(&(objectCategory=Computer)(Name=$ComputerName))"

$DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$DirectorySearcher.Filter = $Filter

$SearcherPath = $DirectorySearcher.FindOne()

#---------------------------------------

$machine = $SearcherPath.GetDirectoryEntry()

write-host "editing property $PropertyToEdit to have $EditedInfo"
#edit the property
#$machine.$PropertyToEdit = $EditedInfo

$machine.InvokeSet(($PropertyToEdit),(($EditedInfo).tostring()))

write-host "committing changes"
#commit the edit on
$machine.CommitChanges()

}

####################################################################################
# Encrypts TXT using public key
# Encrypt-Asymmetric -ClearText "CLEAR TEXT DATA" -PublicCertFilePath "C:\Scripts\PowerShell\Asymmetrical-Encryption\PowerShellAsymmetricalTest.cer" 
####################################################################################
Function Encrypt-Asymmetric {
    [CmdletBinding()]
    [OutputType([System.String])]
    param(
        [Parameter(Position=0, Mandatory=$true)][ValidateNotNullOrEmpty()][System.String]
        $ClearText,
        [Parameter(Position=1, Mandatory=$true)][ValidateNotNullOrEmpty()][ValidateScript({Test-Path $_ -PathType Leaf})][System.String]
        $PublicCertFilePath
    )
    # Encrypts a string with a public key
    $PublicCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($PublicCertFilePath)
    $ByteArray = [System.Text.Encoding]::UTF8.GetBytes($ClearText)
    $EncryptedByteArray = $PublicCert.PublicKey.Key.Encrypt($ByteArray,$true)
    $Base64String = [Convert]::ToBase64String($EncryptedByteArray)
 
    Return $Base64String
 #reference: http://jeffmurr.com/blog/?p=228
}


# Sanity check the two password lengths:
if ($MinimumPasswordLength -le 3) { $MinimumPasswordLength = 4 } 
if ($MaximumPasswordLength -gt 127) { $MaximumPasswordLength = 127 } 
if ($MinimumPasswordLength -gt 127) { $MinimumPasswordLength = 127 } 
if ($MaximumPasswordLength -lt $MinimumPasswordLength) { $MaximumPasswordLength = $MinimumPasswordLength }

# Confirm that this process has administrative privileges to reset a local password.
$CurrentWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$CurrentPrincipal = new-object System.Security.Principal.WindowsPrincipal($CurrentWindowsID)
if (-not $? -or -not $CurrentPrincipal.IsInRole("Administrators")) 
   { write-statuslog -m "ERROR: This process lacks the privileges necessary to reset a password." -exit }

# Confirm that the target local account exists and that ADSI is accessible.
if ($LocalUserName -match '[\\@]')  { write-statuslog -m "ERROR: This script can only be used to reset the passwords of LOCAL user accounts, please specify a simple username without an '@' or '\' character in it." -exit }  
try 
{ 
    $ADSI = [ADSI]("WinNT://" + $env:ComputerName + ",computer") 
    $User = $ADSI.PSbase.Children.Find($LocalUserName)
    $User = $null
    $ADSI = $null 
}
catch 
{ write-statuslog -m "ERROR: Local user does not exist: $LocalUserName" -exit } 


# Generate and test new random password with min and max lengths.
$newpassword = "ConfirmThatNewPasswordIsRandom"

if ($MinimumPasswordLength -eq $MaximumPasswordLength)
{  
#    $newpassword = Generate-RandomPassword -Length $MaximumPasswordLength
 $newpassword = Generate-Password -len $MaximumPasswordLength

} 
else
{ 
#    $newpassword = Generate-RandomPassword -Length $(Get-Random -Minimum $MinimumPasswordLength -Maximum $MaximumPasswordLength) 
 $newpassword = Generate-Password -len $(Get-Random -Minimum $MinimumPasswordLength -Maximum $MaximumPasswordLength)

}

# Users outside USA might modify the Generate-RandomPassword function, hence this check.
if ($newpassword -eq "ConfirmThatNewPasswordIsRandom") 
{ write-statuslog -m "ERROR: Password generation failure, password not reset." -exit } 


#encrypt password 
$encryptedPassword = Encrypt-Asymmetric -ClearText "$newpassword" -PublicCertFilePath "$CertificateFilePath"
 
#if ($encryptedPassword -not $?) { write-statuslog -m "ERROR, password was not encrypted, password not reset." -exit } 


# Attempt to reset the password.
if ( Reset-LocalUserPassword -UserName $LocalUserName -NewPassword $newpassword )
{
    remove-variable -name newpassword  #Just tidying up, not really necessary at this point...
    write-statuslog -m "SUCCESS: $LocalUserName password reset."  
}
else
{
    # Write the RESET-FAILURE file to statuslog; these failure files are used by the other scripts too.

    write-statuslog -m "ERROR: Failed to reset password:`n`n $error[0]" -exit 
} 

#now write the encrypted password($content) to the machine's AD attribute($Property), appending today's date on the front
 $Property = "carLicense"
 $TodaysDate=(GET-DATE -Format s)
 SendAttribute-ToAD -PropertyToEdit $Property -EditedInfo "$TodaysDate $encryptedPassword"
# remove-variable -name encryptedPassword  #Removing Variable, just in case.

# FIN



Wednesday, April 2, 2014

Tripple boot mac, yet another web page on it.....

At work, they have given me a hand-me-down three year old mac with a broken screen to use as my laptop.  Making the best of things, I wanted to tripple boot it with OSX mavericks, Windows 8.1, and Kali Linux.


I won't get into great detail about the steps I took, as you can find a bazillion other sites to explain most of the process.  I could not find a solution to a few spots, so I will elaborate on those.


1)Installed mavericks, install REFIND  (the newer version of reFIT)
2)Use "bootcamp assistant"... BUT INTERRUPT BOOT TO WINDOWS, BOOT TO OSX INSTEAD.
3)Open disk utility, and delete the bootcamp partition, create two MORE partitions.  Format them in exFAT, call them BOOTCAMP and "whatever you want your Linux partition to be called for now."
 4) reboot, booting into windows using a DVD  (I know... but I couldn't get the USB to boot properly)
5) in windows, select the bootcamp partition.  it will say "cannot install here" or some such thing.  FORMAT that partition, then windows will be ok with it and will install.
6) update windows, if you want, or don't.... whatever.
7) after a reboot, make sure OSX still works.  (if REFIND doesnt pop up, you can hold down "option" at the "mac tone" and force it to boot to something other than windows.  Reinstall REFIND to make it work again.)
8) boot the machine again to kali.
9)If you miss the grub menu, it might fail... it did on me.
10) so reboot it again, this time, select "text install"
11) at the point where you want to select the HDD or storage, make sure to do it "manually"
12) find the partition you created for LINUX, and remove it. 
13) then create a partition that is "do not use" at the "beginning of the free space" of 1MB
14) create two more partitions, one that is EXT3 or whatever you like, mount it as "/".  the second one needs to be for SWAP.
15) Finish installing it.
16)  if it boots, you are good, skip to the later point if you windows drive will not boot.
17) when it doesn't boot (mine said "waiting for /dev to populate" forever), catch the grub menu, and do the failsafe option.  If it does still not boot, add "nouveau.modeset=0" at the end of the line that says "ro quiet" .
18) connect it to the Internets, then perform an apt-get update, and upgrade, and dist-upgrade.  This may solve part of your issue.  if not.....
19) install the nvidia drivers:
"apt-get install -y linux-headers-$(uname -r)
apt-get install nvidia-kernel-dkms"
My install took care of uninstalling the "generic" drivers, as listed on other web help pages.
20)  Now that you have a kali install that works, let's boot into windows.
21) if you are staring at an error or a blinking cursor like I was, the boot partion/UFEI is all messed up.
22) Boot to OSX
23) install gdisk (gpt-disk)
24) run sudo gdisk /dev/diskx....   I only had one drive, so it was sudo gdisk /dev/disk0
25) type "b" to back up the partition table
26) now hit "r" and "p".  take note of the partition numbers of the three installs.
27) Enter ‘h’ to recreate your hybrid MBR. Enter each partition number you want (mine were 2 4 6). It will then ask you for a bunch of settings:
Place an EFI partition first: yes/y; For each partition, make bootable: no; For each partition, hex values: AF for OS X, 07 for Windows, 83 for Linux.
28) type "w" to write it.
29) reboot once, just to be sure, go back to OSX
30) if REFIND didn't appear, reinstall that too.
31) enjoy your mac, even though it only runs OSX 30% of the time.

 -AR
"Your mileage may vary, I only wrote this to remind myself how I did it, so if you read it and do something stupid to your own box I take no responsibility.  This is a private note to myself that I have published publicly."

REFERENCES:
http://www.rodsbooks.com/refind/
http://docs.kali.org/general-use/install-nvidia-drivers-on-kali-linux
http://irvanjit.wordpress.com/2013/06/30/triple-booting-mac-os-x-10-8-mountain-lion-windows-8-and-ubuntu-13/








Tuesday, June 26, 2012

Well, it could have been much worse.


I thought I would share a hyper-v war stor.

Yesterday someone from central IT called me, as he was going to update SCVMM to 2012.  I said, sounds great!  It wasn’t.

We believed that it shouldn’t bring anything down, as SCVMM mostly just monitors, so it shouldn’t be a big deal at all.  About 3 hours later, I get a call from my DBA.  Production SQL is down, along with a host of other VMs.  The dreaded “missing config file” error.  Now, I should mention that my vms are on a 3 node Win 2k8 R2 DC cluster.  Rebooting physical machines, and moving the drives around to “working” nodes didn’t work.  I could still browse to the VHDs and the config files.  Hyper-v then reported that there was a problem with a corrupted file.

So as we sitting around, thinking about backup tapes and considering how to update our resume, I remembered that once I just had rebuilt the config file for a machine that did this in the past.  Now this current machine that was failing to start had several pass through disks, memory settings, various NIC configurations that I didn’t want to have to recreate.  I decided to look into the XML config file.  Sure enough, it ended with :
“<settings>
    <global>
      <logical_id type="string">78F….D-4FC2-someotherGUIDdigitshereFB</logical_id>
    </global>
    <memory>
      <bank>
        <limit type="integer">12288</limit>
        <reservation type="integer">12288</reservation>
        <size type="integer">12288</size>
      </bank>
    </memory>
    <processors>
      <count type="integer">4</count>
      <features>
        <limit type="bool">True</limit>
      </features>
      <limit type="integer">100000</limit>
      <limit_cpuid type="bool">False</limit_cpuid>
      <reservation type="integer">0</reservation>
      <weight type="integer">200</weight>
    </processors>
    <stopped_at_host_shutdown type="bool">False</stopped_at_host_shutdo
“

Now I am no programming wiz, but I know that you at least have to close XML tags, or computers get angry.  Some quick googlin’ turned up:


So I made a backup copy of the current broken XML doc, then properly ended the XML tags that were missing.  I then crossed some fingers, right clicked “bring online” and POOF! It worked.
My heart started beating again, and my cell phone quit vibrating.


Tuesday, September 6, 2011

Xserve and Vtrack Visio stencils, free!

I find it strange that after an hour or so searching the internet... no one has free Apple Xserve and Promise Vtrack Visio stencils.  I needed them for a diagram at work, so I commisioned thier creation.... and I would like to release them to the world!  http://www.mediafire.com/?wn61le8um0iqjty is where you can find them.  It has the front and back of both a Promise Vtrack, and an Apple Mac Xserve G5.  (You know, the servers they quick making because they don't give a damn about the enterprise market anymore.)  Please feel free to copy them and distribute, just please let them remain free.  (Dare I say, open source?)  Credits for actual creation go to Tatso, he is far handier in Visio than I am.

--AR

Wednesday, December 8, 2010

3 hours = worlds longest command line

This was on one line, thought I would share it with everyone:

msdeploy -verb:sync -source:"metakey=lm/w3svc/571459,computername=server1" -dest:"metakey=lm/w3svc/2989,computername=server2" -skip:"objectName=metaProperty,attributes.name=LogFileDirectory" -skip:"objectName=metaProperty,attributes.name=SSLStoreName" -skip:"objectName=metaProperty,attributes.name=SSLCertHash" -skip:"objectName=metaProperty,attributes.name=SSLStoreName" -skip:"objectName=metaProperty,attributes.name=ServerBindings" -skip:"objectName=metaKey,attributes.path=blahTOBlah" -skip:"objectName=metaKey,attributes.path=HTTPtoHTPPS" -skip:"objectName=metaKey,attributes.path=redirectToBLAH" -skip:"objectName=metaProperty,attributes.name=AppFriendlyName" -skip:"objectName=metaProperty,attributes.name=SecureBindings" -skip:skipAction=delete -replace:"objectName=metaProperty,match=m:\websitelocation1,replace=x:\websitelocation1" -replace:"objectName=metaProperty,targetAttributeName=value,match=apppool2\.0,replace=apppool" -replace:"objectName=dirPath,match=m:\website1,replace=x:\website" -enableLink:AppPool -disableLink:ContentExtension -whatif > msdeploysync.log



Ouch.
--Bryan

Tuesday, December 7, 2010

Microsoft finally follows it's own RFC... now stuff is broken.

We have a web service that goes out and talks to other web services. Our web service and the other ones are protected by firewalls, as we don't want just anyone hitting our web services. As we move to windows 2008 r2, we noticed something funny was happening..... our connections were being blocked.
Turns out that Microsoft is finally following their own RFC and it is breaking things.  Windows servers now will use the "IP address most closely matching the gateway" to decide what IP address to use as the default one.  So now our webservice was using the "lowest" ip address we had, which was for a site that had nothing to do with the webservice.
I found out I wasn't alone being surprised by this new "feature" and found that there is a workaround.
In short, you need to:
-Download and apply the hofix. (the MS extractor was currupt, so I used 7zip to extract the files)
-Reboot for the hotfix to take effect.
-Gather a list of all your IP addresses on that machine, take out the one you want to be the "default IP." Put them in the variable $currentIPs.  Then you can run the script as below, it will remove and add the IPs all at once with little downtime.

I forgot to remote desktop using the FQDN, so I was disconnected, but when I reconnected everything was happy.


$currentIps = "10.1.1.1","10.1.1.2","10.1.1.3","10.1.1.4"


foreach ($ip in $currentIps){

netsh interface ip delete address public $ip
write-host "$ip deleted"
netsh interface ip add address "public" $ip 255.255.255.0 skipassource=true
write-host "$ip added"
}
Write-Host "I suggest you reboot your server now, just in case."


Notice the "skipassource=true."  This will not work before the hotfix.  Again you do not want to run that parameter with your IP address that you DO want to be the default one.
(My Subnet mask is 255.255.255.0, if yours is different, then change it above.)

Monday, November 29, 2010

Windows Auditing can be annoying. (Shut up already)

My audit logs were filling up with a bunch of B.S. from perfectly good packets being successfully sent and received. (event id 5157, and 5152) By default, Windows thinks you want all of these packets logged... and perhaps some admins do. But they can be logged in the firewall log, I don't want them in the event log too. (Default location of the Windows Firewall log is at "C:\Windows\system32\LogFiles\Firewall\pfirewall.log") So after a bunch of googleing, I found several answers that almost worked. Here is what really worked for me on Windows 2008 R2 and R1:


auditpol /set /subcategory:"Filtering Platform Packet Drop" /success:disable /failure:disable

auditpol /set /subcategory:"Filtering Platform Connection" /success:disable /failure:disable

So there you go, save some audit log space for something that matters, like non-firewall stuff.
-Bryan

(oh, and one more thing, if you want to create a Group policy for this, it is under
computer configuration --> policies --> windows settings --> security settings --> advanced audit policy configuration --> audit policies --> object access. Then double click "Audit Filtering Platform Connection" and check only the box next to "configure the following audit events." DO NOT CLICK THE OTHER TWO BOXES. Repeat for "Audit Filtering Platform Packet Drop" too. If this does not work, edit your GPO to include the policy outlined in Method 1, steps 2 and 3 from http://support.microsoft.com/kb/921468 .  REMEMBER, THE GPO MIGHT TAKE SOME TIME, so if you don't reboot, give it at least 90 min before you give up on the GPO idea.)

Friday, August 27, 2010

trick POSH into modifying the security's username

Sometimes you have to find a way around things. When you get creds from POSH, it leaves a "/" in the username, so you cannot just pull out the username for use in something that is non-microsoft. Well you can trick it into modifying it by copying it out into a new object. I am not smart enough to figure this out, a coworker of mine did though. I give full credit to him for figuring this out, as we could not find anyone on the internet who had.
So the story is, I wanted to copy our subversion code repository from the REPO server over HTTPS to the local box to update the websites on it. We didn't want to put any passwords in the file, so we wanted to use the operator's MS domain username and password. It is important to note that our domain name has three letters, so we pull 4 out of the credentials. If your domain is more or less, you will have to pull out more or less.

#########################################################
#
# Script to copy Machine and Webconfigs from the ... repository to the local host.
#
# Created Aug 18, 2010
# Bryan Loveless 
#  Props to "Catatonic Prime" for figuring out the Creds object thing
#
#
# Requires Powershell 2.0
#
# Change your Execution policy to RemoteSigned if running locally
# by: Set-executionpolicy -executionpolicy RemoteSigned
#
#Prereqs: Run on local machine runnning as THE administrator.  (right click, run as)
#
#Caviots:  If the files dont seem to renew, make sure the repo on ... is updated
#          by running the svn update bat file in the root of C 
#   called "...." .
#   Also, if it doesnt run as a script, you can copy/paste into POSH cmd line.
#  
#
########################################################

#import the bitstransfer module to transfer files
Import-Module BitsTransfer

#get user credentials
Write-Host "use ... domain when logging in (123\ABC123)"
$Dirtycreds = Get-credential "123\USERNAME"

#clean up the username, as it doesnt want a / before the username
#one below only removes first character, need 4 removed to preserve domain in $DirtyCreds for later use
#$creds = New-Object -typeName 'System.Management.Automation.PSCredential' -ArgumentList $Dirtycreds.UserName.Remove(0,1),$Dirtycreds.Password
$creds = New-Object -typeName 'System.Management.Automation.PSCredential' -ArgumentList $Dirtycreds.UserName.Remove(0,4),$Dirtycreds.Password


#####refresh common components to update svn on ..., dont have to do if pulling from HTTPS
##$session1 New-PSSession -ComputerName servername.fully.qualified.here
##Invoke-Command -Session $session1 ""filethatcleansupSVN""
#Import-Module BitsTransfer

#set a timestamp to rename the file with, uses seconds so that it can be run more than once a minute
$timestamp = Get-Date -UFormat %Y%m%d%H%M%S

#set the path to the SVN server
$svnserver = "servername.fully.qualified.here"

#ask the user if they want a dev, test, prod, localhost config
$machinetype = Read-Host "What type of machine is this?  (dev, test, prod, localhost)"


#below compares to see what the user wanted, then changes the variable for the path accordingly
switch ($machinetype)
{
dev {$svnpath = "svn/projects/Configuration/Machine%20Configs/IIS7/2.0/Dev/"
$smbpath = "\\$svnserver\c$\Projects\Configuration\Machine Configs\IIS7\2.0\Dev"}
test {$svnpath = "svn/projects/Configuration/Machine%20Configs/IIS7/2.0/Test/" 
$smbpath = "\\$svnserver\c$\Projects\Configuration\Machine Configs\IIS7\2.0\Test"}
prod {$svnpath = "svn/projects/Configuration/Machine%20Configs/IIS7/2.0/Prod/" 
$smbpath = "\\$svnserver\c$\Projects\Configuration\Machine Configs\IIS7\2.0\Prod"}
localhost {$svnpath = "svn/projects/Configuration/Machine%20Configs/IIS7/2.0/localhost_developer/" 
$smbpath = "\\$svnserver\c$\Projects\Configuration\Machine Configs\IIS7\2.0\localhost_developer"}
default {  Write-Host "I dont know what you want. Close this and try again."
break }
}



#set the path to the .net directory on the local machine
$mypath = "C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG"

#rename the old files
rename-item -path "$mypath\web.config" -NewName web$timestamp.config 
rename-item -path "$mypath\machine.config" -NewName machine$timestamp.config 

#copy the files to the correct locations

#HTTPs method below 
start-bitstransfer -Authentication basic -Displayname "grabwconfig" -credential $creds -Source "https://$svnserver/$svnpath/web.config" -Destination $mypath\web.config 
start-bitstransfer -Authentication basic -Displayname "grabmconfig" -credential $creds -Source "https://$svnserver/$svnpath/machine.config" -Destination $mypath\machine.config 

#Below replaced by HTTPS method
#Copy-Item -Path "$smbpath/web.config" -Credential $creds -Destination "$mypath/web.Config"
#Copy-Item -Path "$smbpath/web.config" -Destination "$mypath/web.Config"
#Copy-Item -Path "$smbpath/machine.config" -Destination "$mypath/machine.Config"


# this will only do the part below if a 64 bit machine
$mypath = "C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG"
if (test-path $mypath)
{
#rename the old files
rename-item -path $mypath\web.config -NewName web$timestamp.config
rename-item -path $mypath\machine.config -NewName machine$timestamp.config

#below replaced by HTTPs method
# Copy-Item -Path "$smbpath/web.config" -Destination "$mypath/web.Config"
# Copy-Item -Path "$smbpath/machine.config" -Destination "$mypath/machine.Config"

#pull it from HTTPs
start-bitstransfer -Authentication basic -Displayname "grabw64config" -credential $creds -Source "https://$svnserver/$svnpath/web.config" -Destination $mypath\web.config 
start-bitstransfer -Authentication basic -Displayname "grabm64config" -credential $creds -Source "https://$svnserver/$svnpath/machine.config" -Destination $mypath\machine.config

}


#copy applicationhost.config to the correct location and rename the old one
$mypath = "C:\Windows\System32\inetsrv\config"
$smbpath = "\\$svnserver\c$\Projects\Configuration\Machine Configs\IIS7"
$svnpath = "svn/projects/Configuration/Machine Configs/IIS7/"
rename-item -path $mypath\applicationHost.config -NewName applicationHost$timestamp.config

start-bitstransfer -Authentication basic -Displayname "grabAHconfig" -credential $creds -Source "https://$svnserver/$svnpath/applicationHost.config" -Destination $mypath\applicationHost.config 

#below replaced by HTTPs method
#Copy-item -path $smbpath\applicationHost.config -Destination "$mypath/applicationHost.config"

create a bunch of websites using POSH

#########################################################
#
# Script to Create the websites in all tiers.
#
# Created Aug 20, 2010
# Bryan Loveless 
#
#
# Requires Powershell 2.0
#
# Change your Execution policy to RemoteSigned if running locally
# by: Set-executionpolicy -executionpolicy RemoteSigned
#
#Prereqs: Have physical paths created already.  
#    Also must have at least one site that exists.  Keep the "Default" 
#        one for now.
#
########################################################
import-module webadministration

$physicalpath = "C:\Projects\Websites" 

#New-Item iis:\Sites\$sitename -bindings @{protocol="http";bindingInformation=":80:$sitename"} -physicalPath $physicalpath\$sitename

#list all websites below, IIS names are same as Physical Paths ON PURPOSE!

$listofwebsites = "site1","site2","site3","YouGetTheIdeaRight","wehavelotsmore","butforthisblog","IshortendTheList"

foreach ($site in $listofwebsites)
{
#create the site, associate with physical path. WILL OVERWRITE OLD SITE!
New-Item iis:\Sites\$site -bindings @{protocol="http";bindingInformation="*:80:"} -physicalPath $physicalpath\$site -Force

#Adds the HTTPS port to all sites.

New-WebBinding -Name "$site" -IP "*" -Port 443 -Protocol https

#stop the site after creating it
Stop-Website $site
}

# to see what a site has, try:
# get-webbinding -name "NAMEOFSITE"

Convert an IIS cert to an apache one

Here is a simple powershell script I wrote to convert a "iis" cert to one that apache is happy with to use with SSL:

####################################################


#convert IIS certs to openSSL ones for Apache to use
# openssl is installed with Apache by default.
#
#created May 24, 2010
#Bryan Loveless 
#
#

Write-host "This script assumes you have openssl installed in the C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin Directory 
And your certs are in the C:\Program Files (x86)\Apache Software Foundation\Apache2.2\certs Directory"


####################################################

Set-Location "C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin"

$OrgCert=Read-Host "What is the name of your cert? (Include the .pfx)"

$NewCert= Read-Host "What do you want to name the new one? (Include the .pem) Normally it is apache.key.pem"

$NewKey= Read-Host "What do you want to name the new one? (Include the .key) Normally it is apache.key"

$newkey2= Read-Host "What do you want to name the new one? (Include the .pem) Normally it is apache.cert.pem"

#PS C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin> 

.\openssl.exe pkcs12 -in ..\certs\$OrgCert -nocerts -out ..\certs\$NewCert -nodes

#Enter Import Password:
#MAC verified OK
#Enter PEM pass phrase:
#Verifying - Enter PEM pass phrase:

#PS C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin> 
.\openssl.exe pkcs12 -in ..\certs\$OrgCert -clcerts -nokeys -out $newkey2
#Enter Import Password:
#PS C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin> 
.\openssl.exe rsa -in ..\certs\$NewCert -out ..\certs\$NewKey
#Enter pass phrase for ..\certs\apache.key.pem:
#writing RSA key
 for converting the chain 
#OpenSSL Convert P7B
#
#Convert P7B to PEM
#
#openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
#
#Convert P7B to PFX
#
#openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
#
#openssl pkcs12 -export -in certificate.cer -inkey privateKey.key -out certificate.pfx -certfile CACert.cer
#OpenSSL Convert PFX
#
#Convert PFX to PEM
#
#openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes