Saturday, January 10, 2015

Setting AWS EC2 Instance Attribute DeleteOnTermination from .NET (C#)

Amazon gives us a great SDK to manage their AWS platform but sometimes a lack of documentation can make certain things difficult to find.  This one was not easily found for me online so I thought that I would share.

Each EC2 instance can have one or more volumes and, when attached, each of those volumes has a DeleteOnTermination attribute which determines whether or not AWS will delete your EBS Volume when you terminate your instance.  You can set this attribute when you create an instance (instructions) but once it's been created, you must use CLI, Powershell, or the SDK to change it.

This post will only cover setting this flag via the SDK and I've chosen to use C#.  Here are the prerequisites for the code seen here:

  • Visual Studio (I'm using 2013)
  • Download the AWS SDK for .NET.  There are also many other SDKs here.
  • Create a project using the provided project templates (installed via the SDK) or set a reference to the AWS SDK DLL in your existing project.  By default, the .NET 4.5 version is here:  C:\Program Files (x86)\AWS SDK for .NET\bin\Net45\AWSSDK.dll
  • Get your AWS Access Key and Secret key.  When you login to the AWS console, go to Identity and Access Management (IAM) and you can generate keys for each user.  You can't retrieve the secret key after creation so make note of it in a safe place.
  • Find the EC2 endpoint for your region here 

The DeleteOnTermination flag actually isn't directly on the Instance or the Volume.  It's part of the Block Device Mapping for the instance.  However, these are accessible via an attribute on the Instance so we can still set it with ModifyInstanceAttribute.  Here's the code for a simple class which will set DeleteOnTermination to false for all volumes attached to an instance.


using System;
using System.Collections.Generic;
using Amazon;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace AwsSamples
{
    public class Sample
    {
        /// <summary>
        /// Turn off "Delete on Termination" for all volumes attached to an instance
        /// </summary>
        /// <param name="instanceId">The Instance ID of your EC2 instance, such as i-a4db8e11</param>
        public static void RemoveDeleteOnTermination(string instanceId)
        {
            // Connect to the EC2 API
            AmazonEC2Config config = new AmazonEC2Config();
            config.ServiceURL = "https://ec2.us-east-1.amazonaws.com";
            IAmazonEC2 client = AWSClientFactory.CreateAmazonEC2Client("YOUR_ACCESS_KEY", 
                "YOUR_SECRET_KEY", config);

            // Retrieve the instance information for the request
            DescribeInstancesRequest ec2Request = new DescribeInstancesRequest();
            ec2Request.InstanceIds = new List<string>() { instanceId };
            DescribeInstancesResponse ec2Response = client.DescribeInstances(ec2Request);
            Instance instance = ec2Response.Reservations[0].Instances[0];

            // Build the request to change the instance attribute
            ModifyInstanceAttributeRequest req = new ModifyInstanceAttributeRequest();
            req.InstanceId = instance.InstanceId;

            // Identify which attribute to change
            req.Attribute = new InstanceAttributeName("blockDeviceMapping");

            // Loop through the Block Device Mappings for the instance
            // The way this is written, it will set the flag for all EBS volumes
            foreach (InstanceBlockDeviceMapping mapping in instance.BlockDeviceMappings)
            {
                // Build the BDM specification for the request
                InstanceBlockDeviceMappingSpecification spec = 
                    new InstanceBlockDeviceMappingSpecification();
                spec.DeviceName = mapping.DeviceName;

                // Initialize the EBS specification
                spec.Ebs = new EbsInstanceBlockDeviceSpecification();
                spec.Ebs.VolumeId = mapping.Ebs.VolumeId;

                // Set the new falue for the DeleteOnTermination flag (true/false)
                spec.Ebs.DeleteOnTermination = false;

                req.BlockDeviceMappings.Add(spec);
            }

            // Send the request.  This commits the changes
            ModifyInstanceAttributeResponse resp = client.ModifyInstanceAttribute(req);
            if (resp.HttpStatusCode != System.Net.HttpStatusCode.OK)
            {
                throw new ApplicationException("Unable to modify the instance");
            }
        }
    }
}

Hope this helps!

Friday, May 27, 2011

CRM 2011 IFD: Certificate Name Can Only Be 128 Characters Long

I learned recently that, as of Rollup 1, CRM 2011 On-Premise will only allow certificates to have names of 128 characters long for Internet-Facing Deployment (IFD).  This one was fun to track down but there is a fix (read: hack) at the bottom of this post.

In the hope that this might help you in your quest for better CRM, here's how it played out:

The server configuration was pretty simple and normal, with the possible exception of that last bullet, but we tried it without that also:
  • CRM Web Server (1) running all latest software, joined to corp domain
  • ADFS Server (1) running all the latest software, joined to corp domain
  • Wildcard cert purchased through internet cert issuer for *.mydomain.com
  • We replaced the default self-signed ADFS token-signing cert with our SSL wildcard cert
The first sign of trouble was when we went to configure Claims-based authentication in Deployment Manager.  We put in all of the usual values and then the snap-in crashed when we clicked Apply.  We were immediately sure if this was an issue with the snap-in or an issue with MMC.  So we ran Deployment Manager again and it said that claims-based auth was enabled, so we continued.

Then we configured IFD and all seemed well.  Next, on the ADFS server, we tried to create a Relying Party Trust for CRM.  This wouldn't allow us past.  So we popped open IE and tried to go to https://auth.mydomain.com/FederationMetadata/2007-06/FederationMetadata.xml.  This threw an ASP.net error, so we went to the log file on the CRM server to see what was up.

The error in the Application Event log was "CrmSecurityException: Relying Party Certificate was not found".  So we went through all kinds of checking to ensure that the cert was in the Personal and Trusted CA store on both servers and that the CRM app pool account had access.  We finally hit a breakthrough when we turned on tracing.  The error in the trace file was pretty much the same as the event log:  "Relying Party Certificate was not found., ErrorCode: -2147220906".  But what was interesting was the line before the error:

Query execution time: 0.0 seconds; database: MSCRM_CONFIG; command: SELECT Id, Name, CertificateData, StoreName, StoreLocation, StoreFindType FROM Certificates  WHERE (((ParentId is null) AND (Type = 'RelyingPartyEncrypting')) ) AND (IsDeleted = 0).

So I looked at the database and sure enough, there was no Relying Party cert in there.  I checked another server where IFD was working and found the record with Type = 'RelyingPartyEncrypting' so it became obvious that the config had failed.  Hence the crashing snap-in in Deployment Manager.  So we decided to trace which that error happened and were delighted to find that error in the trace file also.  We were not, however, delighted with the content of the error message:

Exception creating Certificate, Name=(CN=*.mydomain.com, OU=Domain Control Validated - RapidSSL(R), OU=See www.rapidssl.com/resources/cps (c)11, OU=XXXXXXXXXX, O=*.mydomain.com, C=US, SERIALNUMBER=xxxxxxxxxxxxxxxxxxxxxxxx-wdfpf :Exceeded column length: Column Name)

When I looked in the database at the Certificates table, the Name column where this value is bound is an nvarchar(128).  Our name value for this cert is 162 characters, thanks to all the extra garbage which RapidSSL threw in there.  Then I tried exactly what you would have tried ... I did the unthinkable and resized the database column to 256.  No dice.  Same error in the same place.  I later received some information from a fellow CRM-er (pogo69) that there was also a metadata field which was being checked when Deployment Manager opens.  He suggested a temporary fix for this issue until Microsoft has a chance to release a hotfix.  I have tried it in my client's environment and it appears to work.  


Please note that this is an unsupported change and there could be unintended consequences including causing future Rollups to fail, having future Rollups or hotfixes overwrite (reverse) this change, and causing some unrelated functionality to fail.


You would need to run this in the MSCRM_CONFIG database:



ALTER TABLE Certificates ALTER COLUMN Name NVARCHAR(256);
 
  UPDATE
   MSCRM_CONFIG.dbo.ConfigurationMetadata
  SET
   ConfigurationMetadataXml =
     REPLACE(
      CAST(ConfigurationMetadataXml AS NVARCHAR(MAX)),
      'Name of the Certificatenvarchar128',
      'Name of the Certificatenvarchar256'
     );



Hopefully Microsoft will release a hotfix for this sometime soon.  If you are having this problem, even if this above fix works for you, then please login to Connect and vote up the following 2 issues and add them to your watch list:

Monday, April 25, 2011

CRM 2011: Changing the IFD URL

OK ... so you have an org setup in CRM 2011 On-Premise and now you want to enable Internet-Facing Deployment (IFD).  But when you named the org, you decided to use the name Crm2011UsProd.  That's not going to be a great URL sitting in front of your domain URL: crm2011usprod.mycompany.com.  Your marketing team is hoping for something simple like crm.mycompany.com.  Here's how you can change the IFD public URL it to be whatever you want.


Background
Your IFD URL is always going to be OrgUniqueName.domain.com.  The domain is setup when you first setup IFD and the Unique Org Name is setup when you first create the Org.  If you want to see your unique org name then you can goto Deployment Manager and look in the "Name" column.










When ADFS asks CRM for its endpoints (Relying Party Identifiers), CRM will include an endpoint for each Org.


Prerequisites
You can use any sub domain URL (*.mycompany.com) provided that:

  1. There is no other CRM org in the same instance with the same full URL (same unique name as the sub domain)
  2. It is under the same domain as the ticket service (STS).  So for example you can’t use auth.mycompany.com for the STS and crm.myothercompany.com for CRM.  At least not without some ADFS metadata tricks.
  3. The name can be cleanly mapped to a single network endpoint within your network.  Simply put, it can’t already be mapped to something.
  4. You have a covering SSL cert (either a cert for the exact URL or a wildcard certificate).

Changing the Org Unique Name
In order to change the org unique name, you need to re-import the org under a new name.  Here are the steps involved:







  1. Backup the organization database (OrgName_MSCRM)
  2. Disable the org in Deployment Manager
  3. Delete the org in Deployment Manager
  4. Optional but recommended:  Delete the org database (OrgName_MSCRM) and restore it with the new org name (NewOrgName_MSCRM).  You don’t have to do this but it would keep the org name and database name in line
  5. Import the org and give it the new name
  6. Go into the ADFS MMC console, right-click on the Relying Party Trust and choose “Update from Federation Metadata.  This causes ADFS to go ask CRM for the endpoints again and CRM will answer with all enabled orgs.



Thursday, May 6, 2010

Using Mobile Express for Microsoft Dynamics CRM 4.0 with Blackberry Simulator

Last year, Microsoft released Mobile Express for Dynamics CRM 4.0, a free add-on to CRM which allows almost any web-enabled device to view and update information stored in CRM.  Microsoft included a config page for customizing which allows you to specify which entities are available through the mobile UI and what fields on tse entities are available.  It's very easy to install and configure and comes with a guide that walks you through that.


The installer and documentation can be found here:  http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=f592ec6c-f412-4fd5-9a80-cd3bcbd26d8b.


To get this up and running quickly:

  1. Download and install the bit (no magic here)
  2. Open CRM and goto Setting --> Customization --> Customize Mobile Express
  3. Add any entities which you want to see on the mobile site to the "Selected Entities" and Publish them.
  4. Optionally, you can double-click on any entity and define which fields you want to see in the mobile UI.  If you add/remove any fields, be sure to Publish again.
  5. Append a "/m" to your home CRM server URL to see the site.  So if your server URL is http://domain.com/OrgName, then just goto http://domain.com/OrgName/m.
Don't get your expectations too high for this client, though.  It's designed to be simple but work everywhere.  You can use it on a Blackberry just as easily as an iPhone or a Droid.  If you are demonstrating this to a client or others in your business, you might want to use a Blackberry Simulator.  It shows that you don't need an advanced browser to use this site.

To use a Blackberry Simulator, do the following:
  1. Download the MDS Simulator.
  2. Install the MDS Simulator.
  3. Download a Blackberry Simulator.  It's not terribly important which one you choose but I did have issues getting the older versions (< v4) to work with the current MDS Simulator.
  4. Run the MDS Simulator first and then start the Blackberry Simulator.
The MDS Simulator is required to give your Blackberry Simulator access to the network.

** Note:  Don't use "localhost".  Instead use the IP address of your CRM server (http://10.1.15.88/MyCrmOrg/m)


You should end up with something like this ...




One gripe that I have is that Microsoft has not published the source code up on CodePlex like they did with this product for CRM 3.0.  So customization options beyond turning on/off entities and fields are very limited.

Monday, May 3, 2010

Alternative Identities

If you're wondering why I created the new identity, it stems from my desire to segment my on-air and off-air lives.  I wanted to differentiate the information that I share about Architecture, Dynamics CRM, and SharePoint with the information that I share about climbing Mt Everest, Kite Boarding in Maui, and researching alternative energy sources (at least, I would want to if I had actually done any of those things).

So here begins my quest to be two people at once.