Skip to content
This repository has been archived by the owner on Aug 28, 2021. It is now read-only.

Commit

Permalink
Merge pull request #7 from cmu-sei/launchpoint
Browse files Browse the repository at this point in the history
Launchpoint
  • Loading branch information
sei-jmattson committed Dec 11, 2020
2 parents 1a8b69d + 0e01a83 commit c8f1175
Show file tree
Hide file tree
Showing 31 changed files with 682 additions and 129 deletions.
3 changes: 3 additions & 0 deletions src/TopoMojo.Abstractions/Interfaces/ITopoMojoClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ public interface ITopoMojoClient
Task BuildIso(IsoBuildSpec spec);
Task<string> Templates(int id);
Task<WorkspaceSummary[]> List(Search search);
Task<Registration> Register(RegistrationRequest request);
Task<Challenge> Grade(Challenge challenge);
Task<Challenge> Hints(Challenge challenge);
}

}
42 changes: 42 additions & 0 deletions src/TopoMojo.Abstractions/Models/Registration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2020 Carnegie Mellon University.
// Released under a MIT (SEI) license. See LICENSE.md in the project root.

using System.Collections.Generic;

namespace TopoMojo.Models
{
public class Registration
{
public string SubjectId { get; set; }
public string SubjectName { get; set; }
public string ResourceId { get; set; }
public string GamespaceId { get; set; }
public string ClientId { get; set; }
public string Token { get; set; }
public string RedirectUrl { get; set; }
public Challenge Challenge { get; set; }
}

public class RegistrationRequest
{
public string SubjectId { get; set; }
public string SubjectName { get; set; }
public string ResourceId { get; set; }
}

public class Challenge
{
public string GamespaceId { get; set; }
public ICollection<Question> Questions { get; set; }
}

public class Question
{
public string Text { get; set; }
public string Hint { get; set; }
public string Answer { get; set; }
public float Points { get; set; }
public bool IsCorrect => Points > 0;
}

}
2 changes: 1 addition & 1 deletion src/TopoMojo.Abstractions/TopoMojo.Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<PackageId>TopoMojo.Abstractions</PackageId>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryUrl>https://github.com/cmu-sei/TopoMojo</RepositoryUrl>
<Version>1.3.3</Version>
<Version>1.3.5</Version>
</PropertyGroup>

</Project>
2 changes: 1 addition & 1 deletion src/TopoMojo.Client/TopoMojo.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<PackageId>TopoMojo.Client</PackageId>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryUrl>https://github.com/cmu-sei/TopoMojo</RepositoryUrl>
<Version>1.3.4</Version>
<Version>1.3.5</Version>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
Expand Down
41 changes: 41 additions & 0 deletions src/TopoMojo.Client/TopoMojoClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,47 @@ public async Task<string> Templates(int id)
return await Client.GetStringAsync($"templates/{id}");
}

public async Task<Registration> Register(RegistrationRequest request)
{
var result = await Client.PostAsync("register", Json(request));

if (!result.IsSuccessStatusCode)
throw new Exception();

string data = await result.Content.ReadAsStringAsync();

var registration = JsonConvert.DeserializeObject<Registration>(data);

return registration;
}

public async Task<Challenge> Grade(Challenge challenge)
{
var result = await Client.PostAsync("grade", Json(challenge));

if (!result.IsSuccessStatusCode)
throw new Exception();

string data = await result.Content.ReadAsStringAsync();

var graded = JsonConvert.DeserializeObject<Challenge>(data);

return graded;
}

public async Task<Challenge> Hints(Challenge challenge)
{
var result = await Client.PostAsync("hints", Json(challenge));

if (!result.IsSuccessStatusCode)
throw new Exception();

string data = await result.Content.ReadAsStringAsync();

var hints = JsonConvert.DeserializeObject<Challenge>(data);

return hints;
}
}

}
19 changes: 17 additions & 2 deletions src/TopoMojo.Client/TopoMojoStub.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2020 Carnegie Mellon University.
// Released under a MIT (SEI) license. See LICENSE.md in the project root.
// Copyright 2020 Carnegie Mellon University.
// Released under a MIT (SEI) license. See LICENSE.md in the project root.

using System;
using System.Threading.Tasks;
Expand Down Expand Up @@ -74,5 +74,20 @@ public async Task<ConsoleSummary> Ticket(string vmId)
Url = "/ticket/9876543210"
};
}

public async Task<Registration> Register(RegistrationRequest request)
{
throw new NotImplementedException();
}

public async Task<Challenge> Grade(Challenge challenge)
{
throw new NotImplementedException();
}

public async Task<Challenge> Hints(Challenge challenge)
{
throw new NotImplementedException();
}
}
}
2 changes: 2 additions & 0 deletions src/TopoMojo.Core/CoreOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ public class CoreOptions
public int DefaultTemplateLimit { get; set; } = 3;
public int NetworkHostTemplateId { get; set; } = 421;
public int ReplicaLimit { get; set; } = 5;
public bool AllowUnprivilegedVmReconfigure { get; set; }
public string GameEngineIsoFolder { get; set; } = "static";
public string ConsoleHost { get; set; }
public string DemoCode { get; set; }
public string LaunchUrl { get; set; } = "/lp/?t=";
public JanitorOptions Expirations { get; set; } = new JanitorOptions();

}
Expand Down
1 change: 1 addition & 0 deletions src/TopoMojo.Core/Data/Abstractions/IGamespaceStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public interface IGamespaceStore : IDataStore<Gamespace>
Task<Gamespace> FindByPlayer(int playerId);
Task<Gamespace> FindByShareCode(string code);
IQueryable<Gamespace> ListByProfile(int id);
IQueryable<Gamespace> ListByProfile(string id);
Task<Gamespace[]> DeleteStale(DateTime staleAfter, bool dryrun = true);
}
}
7 changes: 7 additions & 0 deletions src/TopoMojo.Core/Data/Stores/GamespaceStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ public IQueryable<Gamespace> ListByProfile(int id)
.Select(p => p.Gamespace);
}

public IQueryable<Gamespace> ListByProfile(string id)
{
return DbContext.Players
.Where(p => p.Person.GlobalId == id)
.Select(p => p.Gamespace);
}

public override async Task<Gamespace> Load(int id)
{
return await base.Load(id, query => query
Expand Down
4 changes: 3 additions & 1 deletion src/TopoMojo.Core/Data/Stores/_Store.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public DataStore(
DbContext = dbContext;

IdMap = idmap;

ScopedCache = new Dictionary<int, TEntity>();
// _cache = cache;

// _serializeSettings = new JsonSerializerSettings
Expand All @@ -42,7 +44,7 @@ public DataStore(
public TopoMojoDbContext DbContext { get; }
protected IMemoryCache IdMap { get; }
// protected IDistributedCache _cache { get; }
protected Dictionary<int, TEntity> ScopedCache => new Dictionary<int, TEntity>();
protected Dictionary<int, TEntity> ScopedCache { get; }
// protected Dictionary<string, int> IdMap => new Dictionary<string, int>();
// protected JsonSerializerSettings _serializeSettings => new JsonSerializerSettings
// {
Expand Down
7 changes: 7 additions & 0 deletions src/TopoMojo.Core/Exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ public class TemplateLimitReachedException : Exception { }
public class ParentTemplateException : Exception { }
public class WorkspaceNotIsolatedException : Exception { }
public class ActionForbiddenException: Exception { }
public class InvalidClientAudience: Exception { }
public class ResourceNotFound: Exception { }
public class GamespaceNotRegistered: Exception {
public GamespaceNotRegistered() : base() { }
public GamespaceNotRegistered(string message) : base(message) { }
public GamespaceNotRegistered(string message, Exception ex) : base(message, ex) { }
}
}
83 changes: 81 additions & 2 deletions src/TopoMojo.Core/Services/EngineService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private async Task<GameState> Deploy(Data.Gamespace gamespace, GamespaceSpec spe
deployTasks.Add(_pod.Deploy(virtualTemplate));
}

Task.WaitAll(deployTasks.ToArray());
await Task.WhenAll(deployTasks.ToArray());

if (spec.HostAffinity)
{
Expand Down Expand Up @@ -381,6 +381,21 @@ await _pod.ChangeConfiguration(

break;

case "net":

await _pod.ChangeConfiguration(
vmAction.Id,
new VmKeyValue
{
Key = "net",
Value = vmAction.Message
}
);

result = true;

break;

}

return result;
Expand All @@ -396,7 +411,71 @@ await _pod.ChangeConfiguration(
if (search.Take > 0)
q = q.Take(search.Take);

return Mapper.Map<WorkspaceSummary[]>(await q.ToArrayAsync(ct));
return Mapper.Map<WorkspaceSummary[]>(await q.ToArrayAsync(ct), WithActor());
}

public async Task<Registration> Register(RegistrationRequest registration)
{
// check client scope / workspace audience
var workspace = await _workspaceStore.Load(registration.ResourceId);

if (workspace == null)
throw new ResourceNotFound();

if (!workspace.HasScope(Client.Scope))
throw new InvalidClientAudience();

var game = await _gamespaceStore.ListByProfile(registration.SubjectId)
.SingleOrDefaultAsync(m => m.GlobalId == registration.ResourceId);

string id = game?.GlobalId ?? Guid.NewGuid().ToString();
string token = Guid.NewGuid().ToString("n");

var challenge = new Challenge
{
GamespaceId = id,
Questions = new Question[] {
new Question { Text = "What is flag A?" },
new Question { Text = "What is flag B?" },
}
};

return new Registration{
SubjectId = registration.SubjectId,
SubjectName = registration.SubjectName,
ResourceId = registration.ResourceId,
GamespaceId = id,
Token = token,
RedirectUrl = _options.LaunchUrl + token,
ClientId = Client.Id,
Challenge = challenge
};
}

public async Task<Challenge> Grade(Challenge challenge)
{
// TODO: Demo only, implement actual
foreach(var q in challenge.Questions)
{
if (q.Answer.Equals(challenge.GamespaceId))
{
q.Points = 50;
}
}
return await Task.FromResult(challenge);
}

public async Task<Challenge> Hints(Challenge challenge)
{
// TODO: Demo only, implement actual
foreach(var q in challenge.Questions)
{
if (q.Points == 0)
{
q.Hint = "Try the Gamespace Id.";
}
}
return await Task.FromResult(challenge);
}
}
}
Loading

0 comments on commit c8f1175

Please sign in to comment.