Existing role as event target apigateway execution role - c#

I have created an event bus where the target is an existing apigateway. everything working well except the execution role for that particular target. I am using an existing IAM role as an execution role which has both policies attached to it "execute-api:Invoke", "execute-api:ManageConnections". Also assumed by "events.amazonaws.com". But this is not attaching to the target as an execution role. Below is the code to use an existing role
var role = Role.FromRoleName(this, roleId, roleName);
var rule = new Amazon.CDK.AWS.Events.CfnRule(this, ruleId, new Amazon.CDK.AWS.Events.CfnRuleProps
{
EventBusName =busName,
Name = ruleName,
Description = ruleDescription,
EventPattern = eventPattern,
State = "ENABLED",
Targets = new[]
{
new Amazon.CDK.AWS.Events.CfnRule.TargetProperty
{
Id = apiGatewayId,
Arn = apiGatewayArn,
InputTransformer = new Amazon.CDK.AWS.Events.CfnRule.InputTransformerProperty
{
InputPathsMap = inputPath,
InputTemplate = inputTemplate,
},
RoleArn = role.RoleArn,
},
}
});

role.roleArn is undefined because the Role.FromRoleName static method does not perform cloud-side lookups. To consume an imported role's ARN, use fromRoleArn instead. It doesn't perform cloud-side lookups either. It accepts a ARN, without verification.
In fact, all the CDK's various [Something].from....Name|Arn|Attributes static "import" methods behave the same way. They blindly accept what you give them. The returned constructs know what you explicitly told them. Other properties will be undefined.
CDK Context Methods like Vpc.fromLookup do actually perform synth-time "lookups" from your cloud environment and cache the results.
N.B. the ISomething interface constructs returned from import methods are read-only.

You might be better served by using an SDK method to extract and find the information at Synth - if its not something that is going to change between Synth of the template and Deployment, then this is perfectly fine way to do things (and indeed, what is often done behind the scenes)
Also, I notice you're using the Cfn methods. These are L1 constructs - they are bare bones and do not have the necessary hook to slot into most of the ISomething interfaces. Events is not a new library, you shouldn't need to be using CfnRule - there should be Rule just available for you as well. Only with the L2 or L3 constructs can you make use of the handy hooks like passing the construct to another for linking the two. - you really should be using this construct instead (choose your appropriate language) : https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_events.Rule.html

Related

How to build architecture better

I have an ASP.NET Core application which calls a service from another library. The
service works with an external API, which requires a sessionId. We have to call a Login API method to get the sessionId. How long this sessionId lives and when it can be changed - we don't know. Rule is: sessionId can be valid for 1 request, for 10 requests, for 100 requests, can be valid 1 minute, 10 minutes, 1 day... Nobody knows it.
The service has many methods to call similar APIs:
public class BillRequest
{
private readonly HttpClient client;
public BillRequest()
{
client = new HttpClient
{
BaseAddress = new Uri("https://myapi.com/api/v2/")
};
}
public async Task<List<Dto1>> CustomerBankAccountListAsync(int start, int count)
{
List<KeyValuePair<string, string>> nvc = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("sessionId", CURRENT_SESSION_ID)
};
var customerStream = await client.PostAsync("List/CustomerBankAccount.json", new FormUrlEncodedContent(nvc));
var customerString = await customerStream.Content.ReadAsStringAsync();
//....
}
public async Task<List<Dto2>> Method2(int start, int count)
{
List<KeyValuePair<string, string>> nvc = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("sessionId", CURRENT_SESSION_ID)
};
var customerStream = await client.PostAsync("List/Method2.json", new FormUrlEncodedContent(nvc));
var customerString = await customerStream.Content.ReadAsStringAsync();
//....
}
// logic to get SessionId here
public async Task LoginAsync()
{
}
How to implement to save this sessionId inside service?
There are many options to implement:
Call Login method every time before calling a method. Easy to implement, but bad approach, because we have many unnecessary requests then and use the sessionId only once
Save the sessionId on web application level and try to catch exception, when any method gets an 'invalid sessionId' back, and then call Login method, which will return a new sessionId. In this case we have to pass sessionId to constructor of BillRequest class. It works, but I don't like to move responsibility of service to other, because it's internal responsibility of service how to work with API.
Save sessionId inside the service itself and recall Login method inside service, when old sessionId is considered invalid, rewrite it by new etc. But how to save it as "static" in memory? I don't want to save it to any external places (file system, cloud etc), but I can't save to variable of class too, because object of class can be recreated...
I'd suggest certain mental shift here towards functional programming.
Think of sessionID as of a stream of independet values rather than a single object. Then your problem can be redefined in a following (semantically equivalent) way: given a typed stream (string in your case), how to observe its flow and react on incomming changes, which your source code does not control?
Well, there is an answer, proven by an Enterpriseā„¢: reactive extensions.
Techinically such a shift impliest that you're dealing with an IObservable<string> inside of your controller, which either can be injected via the standard .NET Core DI approach, or simply defined by the constructor. That's quite flexible, since rX gives your fully testable, unbelivable powerful toolset to deal with taks of this kind; rX is also compatible with native Task and hence, async/await feature. Nice fact is that it is really easy to inject required behavior from an outerworld and decorate exising observable with a more appropriate one: so, you're safe: once 3rd party's service logic changes, you can adopt your codebase almost instantly and painlessly.
What is gonna be inside that IObservable<string>? Well, I can't say, since you did not give enough information. It might be an interval asking remote server whether current sessionID is still valid and in case not - runs relogin procedure and notifies it's subscrivers about new value; it might be a timer responsible for compile-time known rule of expiration, it might be as sophisticated logic as you need: rX is flexible enough not to limit you on what can be achieved with it as long as you deal with (possible infinite) streams.
As a consequence, it means that you don't need any global value. Just subscribe to a stream of session ids and take latest - the one which is currently valid, do the job and dispose your subscription. It is not expensive and won't hit performance; neither would mess up concurency. Wrap rX into Task and await it, if you'd like to stick to a common .NET fashion.
P.S. 99% of what you would need to deliver an implementation is already there; you just need to combine it.

How to reconfigure SQLTransport based NServicebus in Asp.net Web API?

I am using NServicebus(version 4.6.3) with SQLTransport in my ASP.net web api project. I have different connectionstrings for the queues for different environments (Dev,QA,etc). My configuration looks like below:
public class BusConfigurator
{
public static IStartableBus Bus { get; private set; }
public static void DisposeBus()
{
if (Bus == null)
return;
Bus.Shutdown();
Bus.Dispose();
Bus = null;
}
public static void InitializeServiceBus(string connectionString)
{
var configure = Configure.With()
.DefineEndpointName("MyEndPoint")
.Log4Net(new DebugAppender { Threshold = Level.Warn })
.UseTransport<SqlServer>(connectionString)
.PurgeOnStartup(false)
.SetDefaultTransactionLevel()
.UnicastBus(); // Error is thrown here on second call
configure.MyCustomSQLServerPersistence();
Bus = configure.CreateBus();
}
public static void StartBus()
{
Bus.Start(() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
}
}
I have a dropdown in the app so that the user can select the environment. Based on the selection, I want to reconfigure the bus. So, I call DisposeBus then pass the connection string to the IntializeServiceBus method followed by the startBus. It works first time but throws error below when it gets called again with different connectionstring:
Unable to set the value for key: NServiceBus.Transport.ConnectionString. The settings has been locked for modifications. Please move any configuration code earlier in the configuration pipeline
Source=NServiceBus.Core
Line=0
BareMessage=Unable to set the value for key: NServiceBus.Transport.ConnectionString. The settings has been locked for modifications. Please move any configuration code earlier in the configuration pipeline
Is NServicebus intended to be used/configured this way? (I am guessing probably not) If not then is there a workaround/different approach for this?
In V4 or below, there is no way to do it by normal human means. There is only one Bus per AppDomain. All of the configuration API is static, so if you try, you get exactly the problems you ran into.
By "human means", I mean that it might be possible to do something crazy with spinning up a new AppDomain within your process, setting up a Bus within that, and then tearing it down when you're finished. It might be possible. I haven't tried it. I wouldn't recommend it.
In V5, the configuration API is completely redesigned, is not static, and so this is possible:
var cfg = new BusConfiguration();
// Set up all the settings with the new V5 Configuration API
using (var justOneBus = NServiceBus.Bus.Create(cfg).Start())
{
// Use justOneBus, then it gets disposed when done.
}
That's right. It's disposable. Then you can do it again. In your case you wouldn't want to put it in a using block - you would want to set it up somewhere, and when the dropdown gets switched, call Dispose on the current instance and rebuild it with the new parameters.
Keep in mind, however, that the Bus is still pretty expensive to create. It's definitely still something you want to treat as an application-wide singleton (or singleton-like) instance. You definitely wouldn't want to spin up a separate one per web request.

Dangerous to use Class Scoped vars in TestMethods

I am new to both MOQ and TDD / Unit Testing. I find myself repeating a lot of the same code in my "Arrange" section of each test method and it seems there really ought to be a better way.
First the code that get's oft repeated:
#region Arrange
#region create my Mock Objects
var serviceMock = new Mock<IOrganizationService>();
var factoryMock = new Mock<IOrganizationServiceFactory>();
var tracingServiceMock = new Mock<ITracingService>();
var notificationServiceMock = new Mock<IServiceEndpointNotificationService>();
var pluginContextMock = new Mock<IPluginExecutionContext>();
var serviceProviderMock = new Mock<IServiceProvider>();
#endregion
#region Authentication Stuff
var organizationUri = "http://.../XRMServices/2011/Organization.svc";
var orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(organizationUri));
var credentials = new AuthenticationCredentials();
var username = "USER_ID";
var password = "USER_PWD";
var domain = "MyDomain";
credentials.ClientCredentials. Windows.ClientCredential = new NetworkCredential(username, password, domain);
IOrganizationService service = new OrganizationServiceProxy(orgServiceManagement, credentials.ClientCredentials);
#endregion
#endregion
I considered making custom snippets, constants, etc. but that would not really save the repetitious code just save me some time typing.
Next I thought about scoping everything above at the class level...but some warning bells went off...If the class instantiates once for all test methods then could there be the possibility of variable pollution? Given in the small sample here it really wouldn't happen but I'm trying to think ahead / develop good practices and habits.
What about creating a "Mock & Authentication" object that had all these defined in that object. Then I could have several of these objects with different credentials and my test methods could reference / use just the one variation needed?
So what would be your advice / recommendations for applying some DRY principles to my test cases.
First, your setup is really large. If this is an unit test, this calls for refactoring. Are you sure your components under test do one thing and one thing only? Judging by the names of dependencies, I would assume no.
Next I thought about scoping everything above at the class level...but some warning bells went off...If the class instantiates once for all test methods then could there be the possibility of variable pollution?
No, most test runners create test class instance per test run and unit test frameworks usually allow sort of before test setup, a piece of code (usually method or constructor) that does just this.
In NUnit you got [SetUp] attribute (MS Test uses [TestInitialize] while xUnit uses class constructor):
[SetUp]
public void InitializeDependencies()
{
serviceMock = new Mock<IOrganizationService>();
// ...
}
This is how you usually solve this kind of problems.
What about creating a "Mock & Authentication" object that had all these defined in that object.
While this might be a good idea for authentication part, it certainly is not as sound for mocks. The fact you even consider it rings the refactoring bells once again.

How to keep personalization when moving class derived from WebPartManager to new assembly?

We have a web site project that was started many years ago. The landing page uses personalizable web parts, and the web part manager is an extension of the .NET WebPartManager class, residing in App_Code. The curious thing is that if we move this class into another assembly in the same solution, the personalization is cleared and we can save new personalization. But when we move the class back, it loads the original personalization again. The PathId, UserId, and ApplicationId all appear to stay the same in the asp_PersonalizationPerUser table (See http://msdn.microsoft.com/en-us/library/aa478955.aspx for details.)
UPDATE: The reason I ask is because we need to convert our project to a Web Application project, and we do not want to cause any disruption among some the 500 users that use the application daily. I have put a shelveset together for the conversion and everything seems to be worked out except for this problem.
UPDATE 2: It occurred to me that I need to re-word my question.
How can I keep personalization when moving our class that derives from WebPartManager to a new assembly?
Because the implementation is very complicated and internal to the .NET framework, creating a custom source code to manage this is unfeasible. Instead, running a database script during maintenance will be the best option. Example:
// Read the 'PageSettings' column from the ASP personalization tables
// into a byte array variable called 'rawData' first. Then continue:
var mems = new System.IO.MemoryStream(rawData);
var formatter = new System.Web.UI.ObjectStateFormatter();
var oldState = formatter.Deserialize(mems) as object[];
var index = oldState.ToList()
.FindIndex(o =>
o as Type != null &&
((Type)o).Name.Contains("WebPartManager"));
// In our case, the derivative class name is "MyWebPartManager", you
// may need to change that to meet your requirements
oldState[index] = typeof(WebPartManager);
mems = new System.IO.MemoryStream();
formatter.Serialize(mems, oldState);
var newState = mems.ToArray();
// Write 'newState' back into the database.
In addition to scoping personalization state by user name and path,
SqlPersonalizationProvider supports scoping by application name.
Websites that register personalization providers with identical
applicationName attributes share Web Parts personalization data,
whereas websites that register personalization providers with unique
applicationNames do not. Due to the page-specific and control-specific
nature of personalization data, however, it usually doesn't make sense
to use the same applicationName for Web Parts personalization data
across different websites.
Does your new Web Application project have a different applicationName than the old one?

How can I change part of the composition in MEF after composition?

I've setup my app to have a discoverable security service (ISecurityService) which has a single method IPrincipal GetPrincipal(). Implementers are free to then decide how to get the principal (via domain login, DB etc..). So my app then has parts which do things on startup determined on the roles the user is in, for one example I sections of the interface imported like so:
[Import]
public ISecurityService SecurityService {
get; set;
}
[ImportMany]
public IEnumerable<ISectionPanel> ImportedPanels {
get; set;
}
public ObservableCollection<ISectionPanel> Panels {
get; set;
}
public void OnImportsSatisfied() {
Panels.Clear();
IPrincipal p = Thread.CurrentPrincipal;
foreach (ISectionPanel sp in ImportedPanels.Where(sp => sp.RequiredRole == null || p.IsInRole(sp.RequiredRole))) {
Panels.Add(p);
}
}
Don't concentrate too much on the implementation, this is going to change to annotations later, however, the important thing here that made me crop a gutser was that composition of parts was occurring PRIOR to the security principal being set. What this means is I now have a cat and mouse situation.
I've now solved this by using Lazy<T> on imports which affected the chaining to occur, however if another implementer of a part forgets to use Lazy<T> it may trigger a chained load and cause the app to fail.
What have others used to overcome scenarios such as this?
Previously I had unity which I controlled in a more manual way by simply using RegisterInstance<T>(T t), I've trying to now write apps using the "official" MEF as this comes with the framework and I no longer need to worry about unity.
Ideally what I'd like to be able to do is.
Create parts manually at startup prior composition
Create a composition container manually adding my pre-built parts (like RegisterInstance<T>(T t) in unity
Find remaining parts using the usual methods of composition shown in the docs.
You could initialize your application in two phases:
public static void Main(string[] args)
{
using (var container = new CompositionContainer(...))
{
// phase 1: compose security service and initialize principal
var securityService = container.GetExportedValue<ISecurityService>();
securityService.InitializePrincipal();
// phase 2: compose the rest of the application and start it
var form = container.GetExportedvalue<MainForm>();
Application.Run(form);
}
}
In MEF, what more or less corresponds to RegisterInstance would be the AddExportedValue method. This would work if the host created the security service without using MEF. Since you still want to discover the security service with MEF, something like Wim suggests is probably a good solution.

Categories