Hosting Your Content In The Cloud

Due to same-origin policy restrictions placed by modern browsers and requirements of the SCORM spec, Engine's player and your content will need to be available to your learners on the same domain. When not serving the content files from the same server as Engine, this can be accomplished by hosting Engine's player files on the content's domain or by way of a reverse proxy like CloudFront. If you set up Engine to extract files to your CDN without setting up a solution for these restrictions, you will not be able to launch your courses.

Unzipping Courses to S3

If you are letting Engine handle the management of your course zip files, but you want them to be saved to S3 rather than a content server, you can configure Engine to treat your S3 bucket like a file store.

To use Engine's S3 support, you'll need to specify the value of FilePathToContentRoot to RusticiSoftware.ScormContentPlayer.Logic.DataAccess.FileStorage.DefaultCredentialS3StreamingFileStore|RusticiSoftware.EngineRusticiSoftware.ScormContentPlayer.Logic.DataAccess.FileStorage.DefaultCredentialS3StreamingFileStore and include the following parameters:

  • bucket
  • prefix

Credentials and region will be determined the same way the AWS command line tool would: https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html

For example:

RusticiSoftware.ScormContentPlayer.Logic.DataAccess.FileStorage.DefaultCredentialS3StreamingFileStore|RusticiSoftware.Engine, rustici-tests, engine-content/${TenantName}/

RusticiSoftware.ScormContentPlayer.Logic.DataAccess.FileStorage.DefaultCredentialS3StreamingFileStore, rustici-tests, engine-content/${TenantName}/

You may have noticed that ${TenantName} is included in the example prefix. This is crucial for multi-tenant installations. Engine does not examine the parameters passed in to verify a unique store is set up for each tenant, it's up to you to make sure a unique file store location is established for each tenant.

If you want to also store your xAPI documents on the cloud, you can set the value for xAPIFilesPath in the same way.

However, you should not set FilePathToUploadedZipFile to use an S3 bucket. FilePathToUploadedZipFile is only used as a temporary location for your zip files during the upload process, and the files will be promptly removed at the conclusion of your course's import. Setting this location to use S3 can slow down your import process due to the increased network activity necessary for moving the course files around.

Once you've configured Engine to extract your course files to S3, you'll need to make sure that your WebPathToContentRoot accurately reflects the URL that should be used to access these files. As mentioned elsewhere, this value is often a relative URL for the current domain of the player (e.g. /courses/content/), but it can also be a fully-qualified URL (e.g. http://example.org/courses/content/) if needed.

If you are using a cloud storage solution other than S3 that is inconvenient to mount as a file store on your server, reach out to the Rustici support staff for more information on this solution. We offer an interface call IStreamingFileStore that can be implemented by your team. DefaultCredentialS3StreamingFileStore is an implementation of this interface that ships with Engine for the convenience of our S3-reliant customers, but the interface can be used to interact with just about any cloud storage you would need.

Content Authentication

CloudFront Support

Engine supports adding content authorization cookies via ContentAuthCookieFactory. We provide an implementation for use with Amazon CloudFront. To use Engine's CloudFront support, specify the class 'RusticiSoftware.ScormContentPlayer.Logic.Utilities.CloudFrontCookieFactory`, and the following parameters:

  • path to your downloaded Cloudfront trusted signer private key file (.pem on .NETMust be converted .der format)
  • key pair id
  • seconds for which authorization is valid

Note: You can use OpenSSL with a command like the following to convert the PEM file to the DER format required:

openssl pkcs8 -topk8 -nocrypt -in path/to/CloudFront-PrivateKey.pem  -inform PEM -out path/to/CloudFront-PrivateKey.der  -outform DER

Example ContentAuthCookieFactory value for CloudFront authorization cookies that will expire in 8 hours:

RusticiSoftware.ScormContentPlayer.Logic.Utilities.CloudFrontCookieFactory, /fullpath/to/privatekey.pem, keyPairId, 480

If your application launches Engine's player within an iframe, you might run into issues with the cookies produced by this factory being considered third-party cookies and blocked by some browsers. This type of issue can be circumvented by sending your learner's browser to a page within Engine that will set a placeholder cookie and transparently redirect them to whatever URL you specify. After this page has been loaded in the top-level window, the user's browser will no longer treat cookies set by Engine as third party cookies because the user has visited Engine directly, indicating to the browser that Engine is a trustworthy source.

To do this, send your learners to /SetCookiesAndRedirect.(jsp|aspx) and pass a URL-encoded web path that you would like the learner to be redirected to as the query parameter redirectUrl. Here is an example of a learner's launch link being directed through this page: http://example.com/RusticiEngine/SetCookieAndRedirect.jsp?redirectUrl=https%3A%2F%2Fexample.com%2Fexample%2Fweb%2Fpath

Note:

  • When using content authorization cookies, ideally CourseDirectoryNamingMethod should be set to ApiCourseId and all content would be imported via the API. If not, most content will work properly but Engine will be unable to calculate the appropriate path for multi-AU AICC content (and authorization cookies will not be set for such content).
  • Cross-domain cookies cannot be set. So even if other cross domain issues are solved, the content must be served from the same domain as Engine.

Even if you aren't using CloudFront, you can still secure your content behind an authentication layer that requires cookies. While Engine doesn't provide security for your content on its own, you can configure it to work with your own authentication layer.

In your release package, you will find RusticiSoftware.Engine.dll in the bin folder of the Engine application folderscplogic.jar in the WEB-INF/lib/ of the unpacked RusticiEngine.war. This contains the definition of an interface named ICookieAuthFactory. Using ContentAuthCookieFactory, you can specify your own implementation of this interface, and Engine will use your implementation to set cookies in your learners' browsers during the launch process.

You can determine the values of your cookies using the URI passed into BuildContentAuthCookieValues, or you can use static values in your implementation. The simplest possible implementation would look something like this:

public class ExampleCookieFactory : ICookieAuthFactory
{
    public IDictionary<string, string> BuildContentAuthCookieValues(Uri protectedAbsoluteUri)
    {
        Dictionary<string, string> dict = new Dictionary<string, string>();
        dict.Add("name", "value");
        return dict;
    }
}

public class ExampleCookieFactory implements ICookieAuthFactory
{
    public Map<String,String> BuildContentAuthCookieValues(URI protectedAbsoluteUri) throws Exception {
        HashMap<String,String> dict = new HashMap<String,String>();
        dict.put("name", "value");
        return dict;
    }
}

To configure Engine to use your cookie factory, you will need to provide a setting with the name ContentAuthCookieFactory. The setting value should be the fully qualified class name of your implementation and the assembly name, separated by a pipe character (|)the class name of your implementation. The dlljar containing your implementation should be in the bin folder of the Engine applicationEngine's classpath.

Here's an example value:

<add key="ContentAuthCookieFactory" value="Example.Application.Logic.Authentication.ExampleCookieFactory|Example.Application" />

<entry key="ContentAuthCookieFactory">Example.Application.Logic.Authentication.ExampleCookieFactory</entry>

results matching ""

    No results matching ""