Obfuscating sensitive data in Azure Application Insights

31/05/2022 Leave a comment

While working with a legacy Api which where called via GET request exposing sensitive data in query strings, I saw this sensitive data in Application Insight and wanted to obfuscate them.

This can be done by creating a Customer ITelemetryInitializer, since the API Dependency to the main Application only when this dependency log is made do we want to obfuscate the data, other scenarios can be covered in other ways. With a DependencyTelemetry  it is possible to test if I HTTP request.  If the request do have any query parameter filtering should now be done  from the source list of query strings which is passed in via the constructor. See the code below for the finished QueryStringFilterTelemetryInitializer

using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using System;
using System.Collections.Generic;

namespace Application
{
    public class QueryStringFilterTelemetryInitializer : ITelemetryInitializer
    {

        public QueryStringFilterTelemetryInitializer(IEnumerable<string> queryStringSource)
        {
            QueryStringSource=queryStringSource;
        }

        public IEnumerable<string> QueryStringSource { get; }

        public void Initialize(ITelemetry telemetry)
        {
            var dependencyTelemetry = telemetry as DependencyTelemetry;
            if (dependencyTelemetry == null)
                return;

            if (dependencyTelemetry.Type.Equals("http", StringComparison.InvariantCultureIgnoreCase))
            {
                var uri = new Uri(dependencyTelemetry.Data);
                var queryDictionary = System.Web.HttpUtility.ParseQueryString(uri.Query);
                if (queryDictionary != null || !queryDictionary.HasKeys())
                    return;
                
                foreach (var source in QueryStringSource)
                {
                    var queryValue = queryDictionary[source];
                    if (queryDictionary !=null && !string.IsNullOrEmpty(queryValue))
                    {
                        dependencyTelemetry.Data = dependencyTelemetry.Data.Replace(queryValue, "***********");
                    }
                }
            }
        }
    }
}

With the QueryFilterTelemetryInitializer created we can now instantiate it in our startup.cs file

 public virtual void ConfigureServices(IServiceCollection services)
{
  services.AddSingleton<ITelemetryInitializer>(
             new QueryStringFilterTelemetryInitializer(
                               new List<string>() { "SOMEQUERYSTRING" }));
  
  services.AddApplicationInsightsTelemetry();
  ..
  ..
  ..
}

Instead of providing the list of string at compile time you can also load them in via a config file as shown below

{
 "QueryStrings": [
    "querystring0",
    "querystring1",
    "querystring2"
  ],
}

and in the startup class replace with this line

services.AddSingleton<ITelemetryInitializer>(new QueryStringFilterTelemetryInitializer(Configuration.GetSection("QueryStrings")?.Get<List<string>>().ToArray()));

This is how it will look in the Data in Azure AppInsights

https://URL/API/?queryString0=**********
Categories: .Net, Azure, C# Tags: ,

Sitecore 10 Authenticated File upload to RCE / CVE-2021-38366

10/08/2021 2 comments

After looking for some extreme hardening of the Sitecore client I found a way to get Remote Code execution (RCE) via a Update center, described in this post.

It is possible for authenticated users, to upload arbitrary files, via update package functionality.It is possible for a malicious attacker to bypass file upload restrictions, hardened with the Sitecore hardening guide https://doc.sitecore.com/en/developers/101/platform-administration-and-architecture/security-guide.html and with secure file upload functionality, taken from this link
https://doc.sitecore.com/developers/100/platform-administration-and-architecture/en/secure-thefile-upload-functionality.html.

Test Instance information

The test of this was done on a local Windows 10 machine with Sitecore 10 XM installation, installed via Graphical installation wizard see more information below

System Information
Sitecore version information

The Additional Filed upload restriction package was also installed with the following settings.

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<processors>
<uiUpload>
<processor mode="on"
type="Sitecore.Pipelines.Upload.CheckExtension,
Sitecore.UploadFilter" patch:before="*[1]">
<param desc="Allowed extensions (comma separated)"></param>
<param desc="Blocked extensions (comma separated)">exe,dll,aspx</param>
</processor>
</uiUpload>
</processors>
</sitecore>
</configuration>

Steps to reproduce

Keep in mind this is a autheticated file upload, so a compromised user must be obtained.

  1. Authenticate / Login to Sitecore

2. Once correctly logged in. Navigate to the Upload center

Navigated to update center

3. Choose/click the option to upload custom update

Upload via custom upload

4. Pick your custom webshell

Upload of custom webshell

5. If the installer hangs click anywhere in the windows, this is expected.

Uplaoder timesout / hangs

6. Since uploads of updates packages always goes into the same folder

https://HOSTNAME/sitecore/admin/Packages/

to find the uploaded file in our case
https://sc101cm.dev.local/sitecore/admin/Packages/shell.aspx

7. Now all that is left is running the webshell.

Running our uploaded webshell

Remediation

Disabled the Update center functionality

One way of doing the in add restriction to path in web.config like below

 <location path="sitecore/api/ssc/updatecenter">
  <system.web>
      <authorization>
        <deny users="*" />
      </authorization>
    </system.web>
  </location>

Other

The findings has been reported to Sitecore, and the Update center is being deprecated, but until this happens a simple fix is as mentioned to disabled the Update center functionality.

This vulnerability has been given CVE-2021-38366

Categories: Security, Sitecore Tags: ,

Should you trust your own website ?

15/02/2021 Leave a comment

Let’s start with a question:
Should you trust data downloaded from your own website?

As a rule of thumb NO ! especially not if what you download contains user generated input, as an example data collected from Sitecore Form.

There is something interesting about this, because there is a trust relation for editors to their own site, most editors “i hope” will see their own site as a trustworthy source for downloads, and why shouldn’t they .But is this really true ? In this blog post I will give an example of how Sitecore can be used as a vessel to deliver a malicious payload to an unknown editor “victim”. 

For this I’ve used the latest version of Sitecore 10.0.1 in XM mode.

To enable this let’s assume an editor creates a Form like the one below but it could be any form with fields that allows for text input.

IMG-1-form

Now after publishing the form the attacker sees form “sorry for missing styling:)”

img2

For testing purposes  i will use a very simple payload “=1+1*cmd|’/k echo backdor’!z” which opens an command prompt and display the texst backdoor. More  payloads can be found here https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/CSV%20Injection also note that could be other that are more relevant for other application and not Excel specificly.

The vulnerability used here is better known as csv injection or formula injection

Now after some time the editors want to get the data from his newly created form. He logins into Sitecore and navigates to his form and exports the data “btw only way to view Forms collected data in Sitecore OTB”

Now the next part is he opens the csv file in Excel “please note I’ve enabled what can be seen as an insecure setting in Excel see below.

Now lets see what happens when the editor opens the csv file

Excel does show an alert, and this is where the trust comes into play because why wouldn’t the editor accept the warning and continue.

So now lets see what happens after he accepts the warnings

A nice little command prompt has opened with the text defined in our payload earlier. 

So the question is this a vulnerability in Sitecore ? No or ….. You could filter out characters that could allow these attacks or you could simply add an “‘“ in front of all fields when exported, I will leave it to you to decide, but at least you should tell your customers to regard it as an insecure source when downloading content that contains user generated input. And please MAKE SURE TO DISABLE  “enable dynamic data exchange server launch” in excel. Note this also works for applications then excel., maybe with a different payload.

Categories: Security, Sitecore Tags: ,

Sitecore 9.1 IdentityServer On-Premise AD via ADFS

15/05/2019 90 comments

Which the launch of Sitecore 9.1 came the introduction of the identity server to Sitecore list roles. You can find a lot more information about the Identity Server here https://identityserver.io/- Personally I think this I is great enhancement and add are more easy extendable way of enabling 3 party  authentication providers to Sitecore. As standard the Identity server runs on Sitecore  HOST https://doc.sitecore.com/developers/91/sitecore-experience-management/en/sitecore-host.html And ships with the possibility to use Azure AD and the Identiytserver.Contrib.Membership module  allowing for cloud AD and the old DB style of authenticating in Sitecore. This also means the the old Sitecore AD module is now deprecated and no longer supported. So in this blog post I will show how to integrated a On Premise Ad with  Sitecore Idenityserver hosted on Sitecore Host.

First you need a AD of course and then you need ADFS server to act as a authentication provide to the Identityserver. This however is a little out of scope for this post. But here is two great links on how to configure and forward AD groups as roles

https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-rule-to-send-group-membership-as-a-claim

https://stackoverflow.com/questions/55494354/user-groups-as-claims-through-openid-connect-over-adfs

Before we get to code you need to know about this nuget feed related to Sitcore Identity

https://sitecore.myget.org/F/sc-identity/api/v3/index.json

Since this feed contains some of packages needed. So this project or solution rather is to use OpenId Connect against the with the ADFS server

The solution consist of three class’ i will briefly show them here below

The App Settings classe seen below for retrieving the Setting for the Provider

public class AppSettings
{
public static readonly string SectionName = "Sitecore:ExternalIdentityProviders:IdentityProviders:ADFS";
public ADFSIdentityProvider ADFSIdentityProvider { get; set; } = new ADFSIdentityProvider();
}

The ADFSIdentityProvider which allows for a type strong way of accessing settings related to the module.

public class ADFSIdentityProvider
{
public bool Enabled { get; set; }
public string Authority { get; set; }
public string ClientId { get; set; }
public string AuthenticationScheme { get; set; }
public string MetadataAddress { get; set; }
public string DisplayName { get; set; }
}

And the CongifugreSitecore class which handles the communication with ADFS server

using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Sitecore.Framework.Runtime.Configuration;

namespace Sitecore.IdentityServer.ADFS
{
public class ConfigureSitecore
{
private readonly ILogger _logger;
private readonly AppSettings _appSettings;

public ConfigureSitecore(ISitecoreConfiguration scConfig, ILogger logger)
{

this._logger = logger;
this._appSettings = new AppSettings();
scConfig.GetSection(AppSettings.SectionName);
scConfig.GetSection(AppSettings.SectionName).Bind((object)this._appSettings.ADFSIdentityProvider);
}

public object IdentityServerConstants { get; private set; }

public void ConfigureServices(IServiceCollection services)
{
ADFSIdentityProvider adfsProvider = this._appSettings.ADFSIdentityProvider;
if (!adfsProvider.Enabled)
return;
_logger.LogDebug($"Adding ADFS clientId {adfsProvider.ClientId} Authority {adfsProvider.Authority} Scheme {adfsProvider.AuthenticationScheme}");
new AuthenticationBuilder(services).AddOpenIdConnect(adfsProvider.AuthenticationScheme, adfsProvider.DisplayName, (Action)(options =>
{

options.SignInScheme = "idsrv.external";
options.SignOutScheme = "idsrv";
options.RequireHttpsMetadata = false;
options.SaveTokens = true;
options.Authority = adfsProvider.Authority;
options.ClientId = adfsProvider.ClientId;
options.ResponseType = "id_token";
options.MetadataAddress = adfsProvider.MetadataAddress;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "roles"

};
//Added to enable DEBUG to see all claims
//Can be removed in production
options.Events = new OpenIdConnectEvents()
{
OnTokenValidated = (context) =>
{
//This identity include all claims
ClaimsIdentity identity = context.Principal.Identity as ClaimsIdentity;
//ADD break POINT to see all the claims,
return Task.FromResult(0);
}
};
}));

}
}
}

With the solution build you can deploy this to your Identity Server in sitecoreruntime folder in a production folder. The installationor placement of files should look like below.

isplace

The Sitecore Plugin manifest should point to your assembly name  an example given below.

idenxml1

And for the configuration files placed in Config folder is here an examplereplace clientid and autherityaddress and metaaddress with your own values

identiyseraddfxml2

with that in place you can go ahead and restart the application pool for the identityserver to load in the configurations and you should see the AD login button.

adfslogin

clicking on the button should take you t your ADFS server for authentication, after taht you should be redirect to Sitecore.

Mapping of claims to roles works the same as with Sitecore Azure Ad implementation.

You can find the code for this on github

https://github.com/istern/Sitecore.IdentityServer.ADFS

 

Sitecore installation Framework (SIF) custom install path.

08/02/2019 3 comments

This is a very short post, and properly there exist different ways to achieve the same thing, but this is my take on installing Sitecore 9 in custom path.

As default when downloading the on prem package for Sitecore 9, the installation will install in “C:\inetpub\wwwroot”.

One way of installing all the different sites for a XP installation (cm/cd, XConnect, Identityserver) would be to change the “Site.PhysicalPath” in each *.json file for each role. But foreach installation you would make in the future you would have to edit all the files and change them accordingly.

So instead you could add a new parameter to *.ps1 file used to kick off the installation. But it near the top along side the other parameters needed by the installation framework

1-2019-02-08_08-48-47

Next added it as parameter to the list for SIF parameters

2-2019-02-08_08-37-46

No we have the parameters in place next we need to add updated “Site.PhysicalPath” in each *.json file but we only have to do this once. Changing the line

From
“Site.PhysicalPath”: “[joinpath(environment(‘SystemDrive’), ‘inetpub’, ‘wwwroot’, parameter(‘SiteName’))]”,

TO
“Site.PhysicalPath”: “[concat(parameter(‘InstallDir’), parameter(‘SiteName’))]”,

Last thing needed to do is to update the installation json fil. this would be the topologyenv.json fx. XP0-SingleDeveloper.json with the parameter

2019-02-12_12-45-58

For all future installation all we have to do is changing the $rootPath  parameters in the *.ps1 file to install Sitecore in a custom location.

Categories: Sitecore 9 Tags:

Running Sitecore 9 Field Editor from a Command in Sitecore 9 Experience editor

20/11/2017 Leave a comment

So I’ve have a post about this topics for the last couple of Sitecore Versions so of course it would make sense to have one for Sitecore 9 as well.
Start by navigating to ” /sitecore/content/Applications/WebEdit/Ribbons/WebEdit/Page Editor” in the core database. From here you can duplicate one of the existing chunk or you can create a new one.

 

 

Under your chunk create a new Button for this example I’ve used a “Sprite Large Button”. On the button you can set tootltip and a title for the button. As a field to supply the which Fields is being edited I’m using the id, with the FieldName-Fieldname-Fieldname– I’m using the “-” as a seperated between fields, and “–” to end fieldname section. See image below

 

 

 

In the Sprite section of the button you define the image to be shown in the experience editor.

 

 

Now on the presentation details for the Button

 

 

There are two important section on is the event section which holds what command is triggered

 

 

The other one the path to your script file

 

 

With Sitecore setting part in place.
You can now add the following javascript for convenience if just added the launchfielditor javascript to the root of the site


define(["sitecore", "/-/speak/v1/ExperienceEditor/ExperienceEditor.js",
"/-/speak/v1/ExperienceEditor/ExperienceEditor.Context.js"
, "/-/speak/v1/ExperienceEditor/ExperienceEditorProxy.js"],

function (Sitecore, ExperienceEditor, ExperienceEditorContext,ExperienceEditorProxy) {
Sitecore.Commands.LaunchFieldEditor =
{
canExecute: function (context) {
//YOU COULD ADD FUNCTIONALITY HERE TO SEE IF ITEMS HAVE THE CORRECT FIELDS blog.istern.dk
return true;
},
execute: function (context) {
var rawString = context.button.attributes.name;

var fields = rawString.substring(0,rawString.indexOf("--"))

var fieldsString =fields.replace(new RegExp("-","g"), "|");

var itemId = context.currentContext.itemId.replace("%7b","{").replace("%7d","}")

ExperienceEditorProxy._pe().postRequest('webedit:fieldeditor(command='+itemId+',fields='+fieldsString+',id='+itemId+')', null,false)

}

};
});

And the outcome of the above can be seen here

 

 

Only thing not happening is out save when the editor closes. But I hope to get that part in place soon.

Categories: Javascript, Sitecore 9 Tags:

Easy unit testing in Sitecore with AutoFixture, NSubstitute and Xunit

03/04/2017 Leave a comment

Unit testing Sitecore code has been around for quite som years now, and with the release of version 8.2 Sitecore has implemented a lot of new abstractions, which makes testing of Sitecore code easier. So if you not on 8.2 yet this might not be for you, or this could be a reason for upgrading to 8.2. Today there exists a couple of framework that will help developers with writing unit test to Sitecore one of the more known ones I Sitecore FakeDb. But as we shall see in the following a good portion of the more simple Sitecore API can easyli be test without, but creating test stubs can quick become a cumbersome tasks, and this is exactly where this post comes into play.

Let me briefly introduce AutoFixture

This is take from The AutoFixture Github pages https://github.com/AutoFixture/AutoFixture

AutoFixture is an open source library for .NET designed to minimize the ‘Arrange’ phase of your unit tests in order to maximize maintainability. Its primary goal is to allow developers to focus on what is being tested rather than how to setup the test scenario, by making it easier to create object graphs containing test data.

For me Autofixture helps me writing clean Tests where magic values, or test object are hidden away, ie dummy data is something created when the test runs. I strongly encourage you to take a deeper look at Autofixture it is an awesome Library

Okay so how does this combined with Xuint and NSubstitute. Today You can create an Subsitute for a Sitecore Item But it stille take quite som parameters to create the item so you need to create more than one Substitute see the example below.


  var db = Substitute.For<Database>();
  var itemId = ID.NewID;
  var language = Substitute.For<Language>();
  var definition = new ItemDefinition(
  itemId, "itemname", ID.NewID, ID.NewID);
  var data = new ItemData(
    definition, language,
    Sitecore.Data.Version.First, new FieldList());
  var item = Substitute.For<Item>(itemId, data, db);
  return item;

You could in your test have a test factory that just creates this object for you of course.

Enough Skip to the point .. okay lets see where you getting at.

Okay given the following class Which I want to test. All it does is, for the master database get the root item and add a ChildItem, with any TemplateId and return the newly created child.

public class MyClass
{
   private readonly IFactory _factory;
     public MyClass(IFactory factory)
     {
        _factory = factory;
     }

     public Item AddToSitecore()
     {
      Database database = _factory.GetDatabase("master");
      Item rootItem = database.GetItem("/sitecore/content/home");
      Item childItem = rootItem.Add("child", new TemplateID(ID.NewID));
      return childItem;
    }
}

I can write the following test

  using FluentAssertions;
  using NSubstitute;
  using Sitecore.Abstractions;
  using Sitecore.Data;
  using Sitecore.Data.Items;
  using Xunit;


namespace Sitecore.AutoFixture.NSubstitute
{
  public class MyClassTests
  {

   [Theory, AutoSitecoreData]
   public void MyClass_AddItemToWithAutoFixtureRoot_ShouldReturnItem(Item rootItem,Item childItem,Database database,IFactory factory)
   {
     //Arrange
     database.GetItem("/sitecore/content/home").Returns(rootItem);
     factory.GetDatabase("master").Returns(database);
     rootItem.Add(Arg.Any<string>(), Arg.Any<TemplateID>()).ReturnsForAnyArgs(childItem);
     MyClass sut = new MyClass(factory);

    //Act
    Item returnItem = sut.AddToSitecore();

   //Assert
   returnItem.Should().NotBeNull();
   returnItem.ID.Should().BeSameAs(childItem.ID);
   returnItem.Name.Should().BeEquivalentTo(childItem.Name);
   rootItem.Add(Arg.Any<string>(), Arg.Any<TemplateID>()).Received();
   database.GetItem("/sitecore/content/home").Received();

  }
 }
}

What is nice here is you can the easy created Database and Items (root,and child), and a Sitecore Factory, you can set your expectations in your own test to match what you’re testing.

All with the help of the  AutoSitecoreData Attribute that decorates the tests.

It magically creates new items, database, Sitecore factories, Settings, the last two fund in Sitecore Abstractions. No need for Factories, all you get is relevant data with out static items or

It’s not entirely magic, it extends some AutoFixture attributes, you can have a look at the code at Github

https://github.com/istern/Sitecore.AutoFixture.NSubstitute

 

There Are a few gotchas For this to work in your test, you need to get the code from Github  and build it, Hopefully I will soon build a nuget package which will make this step obsolete . But once build you can reference the SitecoreAutoDataAttribute in your tests. You will also have to reference Sitecore.Kernel but no additional references to Sitecore files is required.

Hope you will find this useful

Categories: Sitecore 8, Unit Testing Tags: ,

Running Sitecore Publishing Service in Docker

08/02/2017 Leave a comment

In this mini series of running Sitecore in docker containers, it is now time to have a look at a container for running Sitecore publishing Service.  This container will setting up the service following the manual process found in the installation guide at dev.sitecore.net. The recommendation specifies that service should be hosted on an IIS so as an base image I will be using the Microsoft/IIS from docker hub.  Over the base image there will be installed dotnetcore hosting using https://chocolatey.org/. Be aware that this docker image will be using windows containers, and you can’t combine linux and windows continer in docker yet. SO !

STOP REMEMBER TO SWITCH TO WINDOWS CONTAINERS

It is important to note that this container is not being packed with the Publishing Service zip file, but instead a voluome should be created with the publishing service files found in the zip. To be clear this means that you will still have to download and extract the publishing service from dev.sitecore.net

To help configurering the container a couple of support files is created. First a small powershell script for manipaluting the connectionstrings into the templates file ”sc.global.xml”  which is then copied into to the configuration.

And yes I know the powershell could be written more crisp sorry..

dont.gif

$user = $env:user
$password = $env:password
$server = $env:server
$coredb = $env:coredb
$masterdb = $env:masterdb
$webdb = $env:webdb
$core = '<core>user id='+$user+';password='+$password +';Data Source='+$server+';Database='+$coredb+';MultipleActiveResultSets=True;</core>'
$master = '<master>user id='+$user+';password='+$password +';Data Source='+$server+';Database='+$masterdb+';MultipleActiveResultSets=True;</master>'
$web = '<web>user id='+$user+';password='+$password +';Data Source='+$server+';Database='+$webdb+';MultipleActiveResultSets=True;</web>'</pre>
(Get-Content C:\resources\sc.global.xml) -replace('{CORE}',$core) | Set-Content C:\resources\sc.global.xml
(Get-Content C:\resources\sc.global.xml) -replace('{MASTER}',$master) | Set-Content C:\resources\sc.global.xml
(Get-Content C:\resources\sc.global.xml) -replace('{WEB}',$web) | Set-Content C:\resources\sc.global.xml

Copy-Item C:\resources\sc.global.xml c:\publishing\config\global\

(Get-IISAppPool "DefaultAppPool" ).ManagedRuntimeVersion = ""

c:\publishing\./Sitecore.Framework.Publishing.Host schema upgrade --force

C:\ServiceMonitor.exe w3svc

And the template xml file

<Settings>
<Sitecore>
<Publishing>
<!--
Overriding & controlling the log level for different parts of the system
-->
<Logging>
<Filters>
<Sitecore>Information</Sitecore>
<Sitecore.Framework.Publishing.DataPromotion>Debug</Sitecore.Framework.Publishing.DataPromotion>
<Sitecore.Framework.Publishing.ManifestCalculation>Trace</Sitecore.Framework.Publishing.ManifestCalculation>
</Filters>
</Logging>
<ConnectionStrings>
{CORE}
{MASTER}
{WEB}
</ConnectionStrings>
</Publishing>
</Sitecore>
</Settings>

 

With the two helper files, all that is left is the Dockerfile


FROM microsoft/aspnet

RUN mkdir C:\publishing
ADD /resources /resources
RUN powershell -NoProfile -Command \
Import-module IISAdministration; \
New-IISSite -Name "publishing" -PhysicalPath C:\publishing -BindingInformation "*:80:"; \
Remove-IISSite -Name 'Default Web Site' -Confirm:$false;

RUN powershell -Command (Get-IISAppPool "DefaultAppPool" ).ManagedRuntimeVersion = ''

RUN powershell -Command Invoke-Expression ((New-Object Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
RUN powershell -Command Install-PackageProvider -Name chocolatey -Force
RUN powershell -Command choco install -y --params="Quiet" dotnetcore-windowshosting
EXPOSE 80

ENTRYPOINT powershell.exe -Command c:\Resources\configure.ps1

 

Once build you should be able to run it.
docker build . -t sitecorepublisging

Remember to mount a volumen pointing to the folder where you extracted the publishingservice.zip file. The volumen needs to point to “c:\\publishing” inside the container. And also supply relevant information for environment variables ie. your sql user name,password and adresse and  Sitecore names for the master web and core so it could looking something like this J

docker run -it -p 80:80 -v d:\\websites\\publishing:c:\\publishing -e “user=sa” -e “password=Sitecore+Docker=Socker!” -e “server=172.29.31.21” -e “coredb=Sitecore_Core” -e “webdb=Sitecore_Web” -e “masterdb=Sitecore_Master” –name demop sitecorpublishingservise

DID YOU REMEMBER TO SWITCH TO WINDOWS CONTAINERS  ?

You can’t use localhost because of some windows natting with docker issues sorrym this is comming in the near future.

Once the container is up and running inspect the container to get the ip.

Docker inspect {containername}

With the ip verify the service is running

http://{CONTAINERIP}/api/publishing/operations/status

you should see a status 0

Once you installed the sitecore package enabling publishing service inside Sitecore. you can copy the the container ip into your configuration found in /App_Config/Include/Sitecore.Publishing.Service.config and update the setting

<setting name="PublishingServiceUrlRoot">http://CONTAINERIP/</setting>

And that’s all. Now you are using the new publishing service with IIS hosted in docker.

lego awesome.gif

Congrats. So test it by publish your entire site i Sitecore 🙂 and be amazed be the publishing service speed.

Once i get around to it i will publish the image to docker hub.  In this blog post i only gave one way to run the publishing service there are of course others. And also the image can be optimised.

Sitecore Docker Solr on windows container

02/11/2016 Leave a comment

Lately I’ve been working on getting Sitecore up and running in docker containers. Which now is possible with windows containers, you can read pbering blog post about here http://invokecommand.net/posts/sitecore-and-docker-today. In my last blog post I showed how to use Solr with Docker and Sitecore, unfortunately you can’t run windows container a long side with Linux containers yet. So in the following I’ve created a windows solr container you can use. Remember this will only work if you  install docker beta.

Simply run

docker run –d –p 8983:8983 istern/windows-solr54 –name mysolr

Since there are some minor bugs on windows container you can’t reference in on localhost so you will have to inspect the container to get the ip.

docker inspect mysolr

paste the ip into your solr host in Sitecore.ContentSearch.Solr.DefaultIndexConfiguration.config  in your environment. And you’re now done.

Categories: Docker, Sitecore 8, Solr Tags: , ,

Solr docker container for Sitecore 8.2

04/10/2016 Leave a comment

For some time, I’ve wanted to work with Docker. So I took on the task of creating a Solr container for Sitecore, a container you can turn on and have all the required Solr Cores configured and preinstalled, so it just works with Sitecore. This post is not a detailed introduction to Docker if you want a detailed introduction I suggest looking at their website https://www.docker.com. This post is only meant to be a simple demo to shown how you could combine Docker with Sitecore. Dont use this container for more than testing, it is not suposed to be used in production.

First I found a  suitable  Docker container image to start from , my choice : the Solr:5.3 found here : https://github.com/docker-solr/docker-solr/blob/dfe2c80ca10ca9191ae8ce7c6193ecd47c6c0b5f/5.3/Dockerfile.

I’ve installed the images “spun up a docker container” pulled  the schema file and ran it through Sitecore 8.2 “enrichment” process. Next I started to build my docker file containing all the configuration for building the container ie configuring the different cores . All that happens is  first to copy in the new schema file  to the basic_configset and afterwards copy the basic_configset to multiple new folders one for each core. See the docker file below

FROM solr:5.3

MAINTAINER istern

ENV SOLR_PATH /opt/solr/server/solr

COPY resources/schema.xml $SOLR_PATH/configsets/basic_configs/conf

RUN cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_core_index && \
echo name=sitecore_core_index > $SOLR_PATH/sitecore_core_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_master_index && \
echo name=sitecore_master_index > $SOLR_PATH/sitecore_master_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_web_index && \
echo name=sitecore_web_index > $SOLR_PATH/sitecore_web_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_fxm_master_index && \
echo name=sitecore_fxm_master_index > $SOLR_PATH/sitecore_fxm_master_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_fxm_web_index && \
echo name=sitecore_fxm_web_index > $SOLR_PATH/sitecore_fxm_web_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_list_index && \
echo name=sitecore_list_index > $SOLR_PATH/sitecore_list_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_marketing_asset_index_master && \
echo name=sitecore_marketing_asset_index_master > $SOLR_PATH/sitecore_marketing_asset_index_master/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_marketing_asset_index_web && \
echo name=sitecore_marketing_asset_index_web > $SOLR_PATH/sitecore_marketing_asset_index_web/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_marketingdefinitions_master && \
echo name=sitecore_marketingdefinitions_master> $SOLR_PATH//sitecore_marketingdefinitions_master/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_marketingdefinitions_web && \
echo name=sitecore_marketingdefinitions_web > $SOLR_PATH/sitecore_marketingdefinitions_web/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_suggested_test_index && \
echo name=sitecore_suggested_test_index > $SOLR_PATH/sitecore_suggested_test_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_testing_index && \
echo name=sitecore_testing_index > $SOLR_PATH/sitecore_testing_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/social_messages_master && \
echo name=social_messages_master > $SOLR_PATH/social_messages_master/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/social_messages_web && \
echo name=social_messages_web > $SOLR_PATH/social_messages_web/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_analytics_index && \
echo name=sitecore_analytics_index > $SOLR_PATH/sitecore_analytics_index/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_core_indexMainAlias && \
echo name=sitecore_core_indexMainAlias > $SOLR_PATH/sitecore_core_indexMainAlias/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_master_indexMainAlias && \
echo name=sitecore_master_indexMainAlias > $SOLR_PATH/sitecore_master_indexMainAlias/core.properties && \
cp -r $SOLR_PATH/configsets/basic_configs/ $SOLR_PATH/sitecore_web_indexMainAlias && \
echo name=sitecore_web_indexMainAlias > $SOLR_PATH/sitecore_web_indexMainAlias/core.properties

You can see the project here at github https://github.com/istern/Sitecore-Containers/tree/master/containers/solr/sitecore8.2  the container image is at dockerhub  at https://hub.docker.com/r/istern/solr-sitecore/

You can test it out  by installing docker and then running the following command.

docker run –name nameofyoucontainer -d -p 8983:8983 istern/solr-sitecore:8.2

You can now reach you solr admin interface on your http://localhost:8983

If you want to add an extra core I’ve made a script you can run from your favorite prompt.

 docker exec [NAMEOFYOURSOLRCONTAINER] ./createcore.sh NameOfNewCore

You could combine the above image with docker compose to have both a solr and mongo running in containers. Below is an example  of a docker-compose.yml

version: ‘2.0’
services:
solr:
image: istern/solr-sitecore:8.2
ports:
– “8983:8983”
mongo:
image: mongo
ports:
– “27020:27017”

you can test it by runnning the following command . The “-d” means as a daemon in he background.

docker-compose up -d

and now you have both a solr and mongo server running as  containers .

A big thanks to @pbering for getting me started and helping m with all my silly docker questions.

Categories: Docker, Sitecore 8 Tags: ,