Önceki makalelerde Windows Azure üzerinde bir bulut uygulamasının en basit haliyle nasıl yapılandırıldığını (“Windows Azure: Yönetim Paneli ve İlk Bulut Uygulaması”), bu uygulamanın SQL Azure altyapısını kullanan bir bulut veritabanı ile nasıl ilişkilendirildiğini (“SQL Azure: Yapılandırma ve İlk Bulut Veritabanı”) gördük. Diğer yandan da Office 365‘in temel ayarlarını ve özelliklerini inceledik (“Office 365’i Yapılandırmak ve Özelliklerine Hızlı Bir Bakış”). Windows Azure-Office 365 entegrasyonu konusunu inceleyen ilk makalemizde Exchange Management Shell’in kullanımını gördük (“Office 365 ve Windows Azure Entegrasyonu 1 – Exchange Management Shell“). Bu makalede anlatılan yöntem beta dönemi için kullanabileceğiniz tek seçenek gibiydi. Dolayısıyla işinizi bir yere kadar görüyordu. Örneğin yaratılan bu kullanıcıya O365 tarafında otomatik lisans atayamıyorsunuz. Belki uygulamanız içine O365 yönetim adresinin linkini verip, kullanıcıyı yaratan kişiyi oraya yönlendirip lisans atama işini manüel yapmasını söyleyebilirsiniz (Lisans atama için “Office 365’i Yapılandırmak ve Özelliklerine Hızlı Bir Bakış” yazıma bakabilirsiniz).
İşin güzel tarafı, O365’in tam sürümü çıktığında, beraberinde bütün bu işlemler ve daha fazlası için faydalı araçlarla geldi: Microsoft Online Services Module for Windows PowerShell. PowerShell için MS Online Modülü ile birlikte PowerShell’i çalıştırarak uzaktan Office 365 hesabınızla ilgili olarak yönetim panelinin grafik arayüzünden yapabildiklerinizin neredeyse tamamını yapabilirsiniz ve altını çizmemiz gereken nokta da güncelleme ve geliştirmelerin sürekli olarak devam ettiği!
Aslında tahmin edersiniz ki bu modül, ev ya da çalışma ofisinizdeki dizüstü veya sunucuya kurulan client ya da server işletim sistemlerine kurulup manüel olarak iş görmeniz için tasarlanmış. Ancak bizim entegrasyon senaryolarımız gereği, bu modülü Windows Azure uygulamamızı barındırdığımız buluttaki sanal makineye kuracağız. Bu yüzden öncelikli olarak Windows Azure bulut uygulamamıza uzaktan masaüstü bağlantısının nasıl gerçekleştirildiğini önceki yazılarımdan (“Bulutta Hibrit Senaryolar – Windows Azure Connect Servisini Yapılandırma“) öğrenebilirsiniz.
Uzaktan Masaüstü Bağlantısı ile bağlı olduğumuz Windows Azure uygulamamızın barındırıldığı sanal Windows Server 2008 R2 SP1 işletim sistemimize aşağıdaki ayarları yapmalıyız:
- PowerShell için MS Online Modülü kullanmaya başlamadan önce sistemde Microsoft Online Services Sign-in Assistant’ın kurulu olması gerekir:
32-bit işletim sistemi için: http://g.microsoftonline.com/0BX00en/500
64-bit işletim sistemi için: http://g.microsoftonline.com/0BX00en/501
- Sonrasında artık Microsoft Online Services Module for Windows PowerShell’i kurabiliriz:
32-bit işletim sistemi için: http://g.microsoftonline.com/0BD00en-US/85
64-bit işletim sistemi için: http://g.microsoftonline.com/0BD00en-US/126
- Windows PowerShell’in hem 32 bit hem 64 bit exe’lerini çalıştırarak Set-ExecutionPolicy RemoteSigned komutunu girip Y diyoruz.
- Uygulamamızın fiziksel olarak tutulduğu E sürücüsündeki approot ve siteroot klasörlerinde Network Service, Everyone, IUSR ve IIS USERS’a Write yetkisi veriyoruz.
- IIS Manager’a girip Application Pool’dan uygulamanın kullandığı uzun-anlamsız-gibi-görünen isme sahip Application Pool’u seçip Advanced Settings’ten, Identity’sini değiştirelim. Normalde varsayılan olarak Network Service seçilidir, ancak bu birtakım erişim hatalarına yol açacağından uzaktan masaüstü bağlantısı yaptığınız kullanıcı adı ve şifresi neyse o bilgileri yeni Application Pool identity’si olarak giriyoruz (Uzaktan bağlandığınız kullanıcı tüm sistemde yazma yetkisine sahip olduğundan herhangi bir yetki sorunu yaşamamayı böylece garantilemiş oluyoruz).
Artık Visual Studio’ya dönüp tek WebRole’lü Windows Azure uygulamamızda C# ile PowerShell scripti yaratıp okumak için gereken kodları yazabiliriz.
Oluşturacağımız yeni bir sayfanın codebehind’ının başına aşağıdaki kütüphaneleri eklemeyi unutmayalım:
using System.IO;
using System.Management;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Runspaces;
Ayrıca önceden alınmış O365 hesabınızın admin yetkisine sahip kullanıcının adını ve şifresini bir yere not edin. Sitenizin tasarımına göre ister textbox’lardan alıp parametre olarak göndererek ister doğrudan kodun içine gömerek bu bilgileri aşağıdaki metotta kullanacağız:
public bool CreateUserOn365(string userPrincipalName, string displayName, string firstName, string lastName, string newPassword, string exactDomain, string companyName)
{
try
{
string credentialID = “admin@pavelslavov.onmicrosoft.com”;
string credentialPW = “Passw0rd”;
string planType = GetO365PlanType(credentialID,credentialPW);
string[] psScript = { @”$pass = convertto-securestring -asplaintext “”” + credentialPW + @””” -force”,
@”$credential = new-object -typename System.Management.Automation.PSCredential -argumentlist “”” + credentialID + @”””, $pass”,
@”Import-Module MSOnline”,
@”Connect-MsolService -Credential $credential”,
@”New-MsolUser -UserPrincipalName ” + userPrincipalName + @” -DisplayName “”” + displayName + @””” -FirstName “”” + firstName + @””” -LastName “”” + lastName + @””” -Password “”” + newPassword + @””” -PasswordNeverExpires $true -ForceChangePassword $false -UsageLocation “”US”””,
@”Set-MsolUserLicense -UserPrincipalName ” + userPrincipalName + @” -AddLicenses “”” + planType + “\””,
“”};
if (File.Exists(common.getPath(“scriptNewUser.ps1”)))
File.Delete(common.getPath(“scriptNewUser.ps1”));
System.IO.File.WriteAllLines(common.getPath(“scriptNewUser.ps1”), psScript);
RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
Runspace myRunspace = RunspaceFactory.CreateRunspace(rsConfig);
myRunspace.Open();
Command command = new Command(common.getPath(“scriptNewUser.ps1″));
Pipeline pipeline = myRunspace.CreatePipeline();
pipeline.Commands.Add(command);
StringBuilder stringBuilder = new StringBuilder();
Collection<PSObject> results = pipeline.Invoke();
// check for errors (non-terminating)
if (pipeline.Error.Count > 0)
{
//iterate over Error PipeLine until end
while (!pipeline.Error.EndOfPipeline)
{
//read one PSObject off the pipeline
var value = pipeline.Error.Read() as PSObject;
if (value != null)
{
//get the ErrorRecord
var r = value.BaseObject as ErrorRecord;
if (r != null)
{
//build whatever kind of message your want
stringBuilder.AppendLine(r.InvocationInfo.MyCommand.Name + ” : ” + r.Exception.Message);
stringBuilder.AppendLine(r.InvocationInfo.PositionMessage);
stringBuilder.AppendLine(string.Format(“+ CategoryInfo: {0}”, r.CategoryInfo));
stringBuilder.AppendLine(
string.Format(“+ FullyQualifiedErrorId: {0}”, r.FullyQualifiedErrorId));
}
}
}
pipeline.Dispose();
myRunspace.Close();
myRunspace.Dispose();
rsConfig = null;
db.Dispose();
//if pipeline has any errors, not exceptions, the user will be created and must be deleted because of the errors
//the following script deletes the user from Office 365
try
{
string[] script = { @”$pass = convertto-securestring -asplaintext “”” + credentialPW + @””” -force”,
@”$credential = new-object -typename System.Management.Automation.PSCredential -argumentlist “”” + credentialID + @”””, $pass”,
@”Import-Module MSOnline”,
@”Connect-MsolService -Credential $credential”,
@”Remove-MsolUser -UserPrincipalName ” + userPrincipalName + ” -force”,
“”};
if (File.Exists(common.getPath(“scriptDeleteUser.ps1”)))
File.Delete(common.getPath(“scriptDeleteUser.ps1”));
System.IO.File.WriteAllLines(common.getPath(“scriptDeleteUser.ps1”), script);
RunspaceConfiguration config = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(config);
runspace.Open();
Command cmd = new Command(common.getPath(“scriptDeleteUser.ps1”));
Pipeline pipe = runspace.CreatePipeline();
pipe.Commands.Add(cmd);
pipe.Invoke();
pipe.Dispose();
runspace.Close();
runspace.Dispose();
config = null;
}
catch (Exception ex)
{
common.CreateLog(ex.ToString());
}
return false;
}
pipeline.Dispose();
myRunspace.Close();
myRunspace.Dispose();
rsConfig = null;
db.Dispose();
return true;
}
catch (Exception e)
{
return false;
}
}
Bu metot ile, bir string array içine satır satır PowerShell komutları giriyoruz. İlk önce O365 şifremizi SecureString’e çeviriyor ve kullanıcı adımızla beraber credential değişkenine atıyoruz. Sonrasında ise yukarıdaki adımlarda yüklediğimiz MS Online modülünü üzerimize import ediyoruz ve Connect-MsolUser cmdlet’iyle kullanıcı ve şifremizi doğrulatarak hesabımıza bağlanıyoruz. New-MsolUser cmdlet’i otomatik olarak kullanıcımızın O365 tarafında girdiğimiz çeşitli parametrelerdeki bilgilerle yaratılmasını sağlıyor. Set-MsolUserLicense cmdlet’i ise önceki adımda yaratılan kullanıcıya lisans atanmasını sağlıyor. Bunun otomatik olması için metodun en başlarında aşağıdaki koda sahip metot çağırılıyor:
public string GetO365PlanType(string credentialID, string credentialPW)
{
try
{
string[] psScript = { @”$pass = convertto-securestring -asplaintext “”” + credentialPW + @””” -force”,
@”$credential = new-object -typename System.Management.Automation.PSCredential -argumentlist “”” + credentialID + @”””, $pass”,
@”Import-Module MSOnline”,
@”Connect-MsolService -Credential $credential”,
@”Get-MsolAccountSku”,
“”};
if (File.Exists(common.getPath(“scriptGetPlan.ps1”)))
File.Delete(common.getPath(“scriptGetPlan.ps1”));
System.IO.File.WriteAllLines(common.getPath(“scriptGetPlan.ps1”), psScript);
RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
Runspace myRunspace = RunspaceFactory.CreateRunspace(rsConfig);
myRunspace.Open();
Command command = new Command(common.getPath(“scriptGetPlan.ps1″));
Pipeline pipeline = myRunspace.CreatePipeline();
pipeline.Commands.Add(command);
StringBuilder stringBuilder = new StringBuilder();
Collection<PSObject> results = pipeline.Invoke();
// check for errors (non-terminating)
if (pipeline.Error.Count > 0)
{
//iterate over Error PipeLine until end
while (!pipeline.Error.EndOfPipeline)
{
//read one PSObject off the pipeline
var value = pipeline.Error.Read() as PSObject;
if (value != null)
{
//get the ErrorRecord
var r = value.BaseObject as ErrorRecord;
if (r != null)
{
//build whatever kind of message your want
stringBuilder.AppendLine(r.InvocationInfo.MyCommand.Name + ” : ” + r.Exception.Message);
stringBuilder.AppendLine(r.InvocationInfo.PositionMessage);
stringBuilder.AppendLine(string.Format(“+ CategoryInfo: {0}”, r.CategoryInfo));
stringBuilder.AppendLine(
string.Format(“+ FullyQualifiedErrorId: {0}”, r.FullyQualifiedErrorId));
}
}
}
pipeline.Dispose();
myRunspace.Close();
myRunspace.Dispose();
rsConfig = null;
return “false”;
}
if (results.Count > 0)
{
stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
foreach (PSPropertyInfo psPropertyInfo in obj.Properties)
{
//get the value of plan type for the given account sku
if (psPropertyInfo.Name == “AccountSkuId”)
stringBuilder.AppendLine(psPropertyInfo.Value.ToString().Trim());
}
}
pipeline.Dispose();
myRunspace.Close();
myRunspace.Dispose();
rsConfig = null;
string output = stringBuilder.ToString().Trim();
return output;
}
else
return “false”;
}
catch (Exception e)
{
return “false”;
}
}
Bu metot ile O365 hesabınıza giriş yapıp Get-MsolAccountSku cmdlet’iyle hesabınızda hangi lisans planını kullandığınızın bilgisi öğreniliyor ve bu bilgi, işlemi yaptıran üstteki metoda gönderiliyor.
İşlemler başarıyla tamamlanırsa, O365 hesabınızın kullanıcı adı ve şifresi ile yaratacağınız yeni kullanıcının sadece ad ve soyadı bilgileri Windows Azure’daki ASP.NET uygulamanızdan girilerek arka planda otomatik olarak O365 hesabınıza provize edilmesi sağlanmış oluyor.
Kodlara daha dikkatli bakarsanız, PowerShell script’leri çalıştırılırken alınabilecek hata mesajlarını da yakalayabiliyoruz, bunları da dilerseniz kullanıcıya gösterebilirsiniz.
O365’in PowerShell ile yönetimi hakkında daha fazla bilgi ve MS Online Module for PowerShell’in mevcut tüm cmdlet’lerinin listesi için buraya ve buraya tıklayınız.
Windows Azure ve O365’in entegrasyonunu anlatmaya devam edeceğim yazılar için takipte kalın!
Bu konuyla ilgili sorularınızı Http://forum.mshowto.org alt kısımda bulunan yorumlar alanını kullanarak sorabilirsiniz.
Referanslar