AWS Route53 Recovery Controller error when getting or updating the control state using .net - aws-sdk-net

I am trying to get Amazon's Route53 Recovery Controller to update control states from a .net application and I keep getting an error. I see on the documentation that I need to set the region and cluster endpoint, but I can't figure out how to do it.
Here a sample of the code I am using:
AmazonRoute53RecoveryControlConfigConfig configConfig = new AmazonRoute53RecoveryControlConfigConfig();
configConfig.RegionEndpoint = RegionEndpoint.USWest2;
AmazonRoute53RecoveryControlConfigClient configClient = new AmazonRoute53RecoveryControlConfigClient(_awsCredentials, configConfig);
DescribeClusterResponse describeClusterResponse = await configClient.DescribeClusterAsync(new DescribeClusterRequest()
{
ClusterArn = "arn:aws:route53-recovery-control::Account:cluster/data"
});
foreach (ClusterEndpoint clusterEndpoint in describeClusterResponse.Cluster.ClusterEndpoints)
{
AmazonRoute53RecoveryClusterConfig clusterConfig = new AmazonRoute53RecoveryClusterConfig();
clusterConfig.RegionEndpoint = RegionEndpoint.GetBySystemName(clusterEndpoint.Region);
AmazonRoute53RecoveryClusterClient client = new AmazonRoute53RecoveryClusterClient(_awsCredentials, clusterConfig);
GetRoutingControlStateResponse getRoutingControlStateResponseWest = await client.GetRoutingControlStateAsync(new GetRoutingControlStateRequest()
{
RoutingControlArn = "arn:aws:route53-recovery-control::Account:controlpanel/data/routingcontrol/data"
});
GetRoutingControlStateResponse getRoutingControlStateResponseEast = await client.GetRoutingControlStateAsync(new GetRoutingControlStateRequest()
{
RoutingControlArn = "arn:aws:route53-recovery-control::Account:controlpanel/data/routingcontrol/data"
});
UpdateRoutingControlStatesRequest request = new UpdateRoutingControlStatesRequest();
request.UpdateRoutingControlStateEntries = new List<UpdateRoutingControlStateEntry>()
{
new UpdateRoutingControlStateEntry()
{
RoutingControlArn = "arn:aws:route53-recovery-control::Account:controlpanel/data/routingcontrol/data",
RoutingControlState = getRoutingControlStateResponseWest.RoutingControlState == RoutingControlState.On ? RoutingControlState.Off : RoutingControlState.On
},
new UpdateRoutingControlStateEntry()
{
RoutingControlArn = "arn:aws:route53-recovery-control::Account:controlpanel/data/routingcontrol/data",
RoutingControlState = getRoutingControlStateResponseEast.RoutingControlState == RoutingControlState.On ? RoutingControlState.Off : RoutingControlState.On
}
};
UpdateRoutingControlStatesResponse response = await client.UpdateRoutingControlStatesAsync(request);
if (response.HttpStatusCode == HttpStatusCode.OK)
{
break;
}
}
When this code executes I get this error when it tries to get the control state: The requested name is valid, but no data of the requested type was found.
I see in the java example you can set the region and the data plane url endpoint, but I don't see the equivalent in .net.
https://docs.aws.amazon.com/r53recovery/latest/dg/example_route53-recovery-cluster_UpdateRoutingControlState_section.html
This works when I use the cli which I can also set the region and url endpoint.
https://docs.aws.amazon.com/r53recovery/latest/dg/getting-started-cli-routing.control-state.html
What am I doing wrong here?

There is a solution to this question here: https://github.com/aws/aws-sdk-net/issues/1978.
Essentially use the ServiceURL on the configuration object and add a trailing / to the endpoint url.
AmazonRoute53RecoveryClusterConfig clusterRecoveryConfig = new AmazonRoute53RecoveryClusterConfig();
clusterRecoveryConfig.ServiceURL = $"{clusterEndpoint.Endpoint}/";
AmazonRoute53RecoveryClusterClient client = new AmazonRoute53RecoveryClusterClient(_awsCredentials, clusterRecoveryConfig);

Related

Identity server stuck in redirect loop

I'm using identityserver4 for single sign-on. For most of the time application function smoothly but intermittently we face a redirect loop issue which becomes a show stopper for us until we restart's our app service. The page goes on loading continuously before finally showing a 'Bad request - Request Too Long' page with message: HTTP Error 400. The size of the request headers is too long. If we check the network tab, we can see that the application is looping between the identity server and client application redirect sign in pages. The application insight tells us that the client app gives a 401 on his home/index page and then a 302 on the signin-oidc url, then goes to the identity server connect/token, then connect/userinfo endpoints to get claims and comes back to the client home/index page to again get a 401. The loop continues (Identity server says user is authenticated while client says it is not). We are unable to find a fix for this since long. Any help is appreciated. Attaching the client side configuration for reference.
Findings
Our client app is an mvc app & we have used Session's & TempData in few area's. This areas are the triggering point of the redirect issue. What we have observed is, when the client initially login the authentication cookie is created (Cookie Name: AudDiscoveryAuth) and I could see it being passed in header for each request made to the controller actions. But once the user visit's any such area where we have used Session/TempData and Log out or any other user tries to login, Identity server successfully authenticates the user also the userendpoint to retrieve the details is being invoked however the cookie itself is not being created and is missing in every request to the Index/Home action method hence the redirect loop. Wondering what could be hampering in issuing cookie when using session variable elsewhere in the application or is their a setting missing.
Also in every redirect the occurrence of OpenIdConnect.nonce.XXX cookie is incremented. Once the count of OpenIdConnect.nonce.XXX reaches more then a certain level we get the bad request error page
public void Configuration(IAppBuilder app)
{
string baseClientAddress = ConfigurationManager.AppSettings["ApplicationUrl"];
int slidingExpiryHrs = Convert.ToInt32(ConfigurationManager.AppSettings["SlidingExpiryHrs"]);
int slidingExpiryMins = Convert.ToInt32(ConfigurationManager.AppSettings["SlidingExpiryMins"]);
TimeSpan expireTimeSpan = new TimeSpan(slidingExpiryHrs, slidingExpiryMins, 0);
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>();
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationType,
CookieName = "AudDiscoveryAuth",
ExpireTimeSpan = expireTimeSpan,
SlidingExpiration = true
});
app.UseOpenIdConnectAuthenticationPatched(new OpenIdConnectAuthenticationOptions
{
ClientId = "ratingspro.web",
Authority = IdsvrConstants.BaseAddress,
RedirectUri = baseClientAddress + "signin-oidc/",
PostLogoutRedirectUri = baseClientAddress + "signout-callback-oidc/",
ResponseType = "code id_token",
Scope = "openid api1 ratingspro.webapi offline_access",
UseTokenLifetime = false,
SignInAsAuthenticationType = DefaultAuthenticationType,
RequireHttpsMetadata = true,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
var client = HttpClientFactory.Create();
var tokenResponse = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
{
Address = IdsvrConstants.TokenEndpoint,
ClientId = "ratingspro.web",
ClientSecret = "secret",
Code = n.Code,
RedirectUri = n.RedirectUri,
});
if (tokenResponse.IsError)
{
LogHelper.LogMessage("RatingsproApp: Startup => tokenResponseError: " + tokenResponse.Error);
throw new AuthenticationException(tokenResponse.Error);
}
var userInfoResponse = await client.GetUserInfoAsync(new UserInfoRequest
{
Address = IdsvrConstants.UserInfoEndpoint,
Token = tokenResponse.AccessToken
});
if (userInfoResponse.IsError)
{
throw new AuthenticationException(userInfoResponse.Error);
}
var claims = userInfoResponse.Claims;
if (claims.Any(c => c.Type == "ApplicationAccessDenied"))
{
throw new AuthenticationException(claims.FirstOrDefault(c => c.Type == "ApplicationAccessDenied").Value);
}
// create new identity
var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
id.AddClaims(claims);
id.AddClaim(new Claim("AccessToken", tokenResponse.AccessToken));
id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString(CultureInfo.InvariantCulture)));
id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
client.Dispose();
n.AuthenticationTicket = new AuthenticationTicket(
new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
n.AuthenticationTicket.Properties);
},
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
n.ProtocolMessage.IdTokenHint = idTokenHint;
}
return Task.FromResult(0);
},
AuthenticationFailed = x =>
{
x.ProtocolMessage.RedirectUri = "/";
return Task.CompletedTask;
}
}
});
}
}

Power BI REST API ExportToFileInGroup Not Working

I am able to programmatically log in to the PowerBI Client, gather my Workspaces as well as get a specific Report from a specific Workspace. I need to programmatically render that report to a .pdf or .xlsx file. Allegedly this is possible with the ExportToFileInGroup/ExportToFileInGroupAsync methods. I even created a very simple report without any parameters. I can embed this using the sample app from here. So that at least tells me that I have what I need setup in the backend. But it fails when I try to run the ExportToFileInGroupAsync method (errors below code.)
My Code is:
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new string[] {
PowerBiScopes.ReadReport,
PowerBiScopes.ReadDataset,
});
var userInfo = await graphServiceClient.Me.Request().GetAsync();
var userName = userInfo.Mail;
AuthDetails authDetails = new AuthDetails {
UserName = userName,
AccessToken = accessToken,
};
var credentials = new TokenCredentials($"{accessToken}", "Bearer");
PowerBIClient powerBIClient = new PowerBIClient(credentials);
var groups = await powerBIClient.Groups.GetGroupsAsync();
var theGroup = groups.Value
.Where(x => x.Name == "SWIFT Application Development")
.FirstOrDefault();
var groupReports = await powerBIClient.Reports.GetReportsAsync(theGroup.Id);
var theReport = groupReports.Value
.Where(x => x.Name == "No Param Test")
.FirstOrDefault();
var exportRequest = new ExportReportRequest {
Format = FileFormat.PDF,
};
string result = "";
try {
var response = await powerBIClient.Reports.ExportToFileInGroupAsync(theGroup.Id, theReport.Id, exportRequest);
result = response.ReportId.ToString();
} catch (Exception e) {
result = e.Message;
}
return result;
It gets to the line in the try block and then throws the following errors:
An error occurred while sending the request.
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
UPDATE
Relating to #AndreyNikolov question, here is our Embedded capacity:
After this was implemented, no change. Same exact error.
Turns out the issue was on our side, more specifically, security/firewall settings. Here is the exact quote from our networking guru.
"After some more investigation we determined that our firewall was causing this issue when it was terminating the SSL connection. We were able to add a bypass for the URL and it is now working as expected."

How to get service fabric nodes that run my stateless service in c#?

In c#, I want to get a list of service fabric node information where my stateless service runs. This will be useful in tests. I know how to do this for stateful service using FabricClient class and ActorServiceProxy class, but when it comes to stateless service, I couldn't find a way. Do you have an idea?
Thanks,
You can still use the FabricClient to get this information. Have a play with the QueryManager to check for the info you need
Here's some quick code I use to quickly query the latest version of our TenantApp Service then I check to see they're all running in a healthy state or they've been upgraded properly.
var currentAppTypes = await fabricClient.QueryManager.GetApplicationTypeListAsync();
var tenantAppTypes = currentAppTypes.Where(x => x.ApplicationTypeName.Equals("TenantAppsType"));
var latestTenantAppType = currentAppTypes.Where(x => x.ApplicationTypeName.Equals("TenantAppsType"))?
.OrderByDescending(x =>
{
var versions = x.ApplicationTypeVersion.Split('.');
if (versions.Length == 3)
{
return (int.Parse(versions[0]) * 1000000) +
(int.Parse(versions[1]) * 1000) +
int.Parse(versions[2]);
}
return 0;
})?.FirstOrDefault();
if (latestTenantAppType != null)
{
var currentSvcTypes = await fabricClient.QueryManager.GetServiceTypeListAsync(latestTenantAppType.ApplicationTypeName, latestTenantAppType.ApplicationTypeVersion);
// etc
}
Or if you just want to get all the applications running
var currentApps = await fabricClient.QueryManager.GetApplicationListAsync();
Once you have the service information you can check the nodes its on or you can check the nodes directly themselves
var currentNodes = fabricClient.QueryManager.GetNodeListAsync();
var nodeInfo = await fabricClient.QueryManager.GetNodeLoadInformationAsync("nodeName");
Hope this helps
For anyone still trying to do this, I had a timer requirement that required me to work out how many nodes were running my app on the fly. This is roughly the code I used:
string currentNodeName = ServiceContext.NodeContext.NodeName;
var fabricClient = new FabricClient();
var nodeList = (await fabricClient.QueryManager.GetNodeListAsync()).ToList();
var serviceName = ServiceContext.ServiceName.LocalPath.Split('/')[1];
var nodesRunningApplication = new List<Node>();
foreach (var node in nodeList)
{
var nodeApplicationList = await fabricClient.QueryManager.GetDeployedApplicationListAsync(node.NodeName);
var nodeApplication = nodeApplicationList.FirstOrDefault(p =>
p.ApplicationName.LocalPath.Split('/')[1] == serviceName);
if (nodeApplication != null)
{
nodesRunningApplication.Add(node);
}
}

Calling WorkFlow Soap Service from PCL

I have a WorkFlow Service hosted in a server: http://myServer.net/MyWorkflowService.xamlx
and it's working normally, I called it from a Windows Phone app before and working.
Now, I wanted to call it from a PCL Project (profile 78) for Xamarin.
I got this error:
A correlation query yielded an empty result set. Please ensure
correlation queries for the endpoint are correctly configured.
I added it as a service reference, and I call an Async Method, and subscribes for completed event:
example
TaskCompletionSource<MyResponse> tsk = new TaskCompletionSource<MyResponse>();
WorkFlowService.SubmitModel serviceModel = new WorkFlowService.SubmitModel()
{
List = MyList.ToArray<string>(),
Guid = Guid,
Description = Description,
userid = UserId
};
WorkFlowClient.SubmitCompleted += (sender, eventArgs) => {
if (eventArgs.Error != null)
{
Debug.WriteLine("Exception : DataService : Adding New" + eventArgs.Error.Message);
tsk.TrySetResult(new MyResponse() {
HasError = true
});
}
else
{
tsk.TrySetResult(new MyResponse()
{
HasError = false
});
}
};
WorkFlowClient.SubmitAsync(new WorkFlowService.SubmitRequest((serviceModel)));
return tsk.Task;
I should send an array of strings with my request, Should I provide ServiceReferences.ClientConfig file and what is the build action for it inside the PCL?!

How to play secure streamed url of asset fetched dynamically through code( In Azure media services)

I am using Azure Media Services and a Silverlight Player to play the streamed url
I am able to ingest, encode the video file as an asset file but when I go play the streamed url I am facing problem.
I use following code to fetch the url...
context = new CloudMediaContext(_accountName, _accountKey);
IAsset myAsset = GetAsset("UUID:7a32b941-30bd-4c96-bf4e-26df5022eec5");
var theManifest = from f in myAsset.AssetFiles
where f.Name.EndsWith(".ism")
select f;
var manifestFile = theManifest.First();
IAccessPolicy streamingPolicy = _context.AccessPolicies.Create("Streaming policy",
TimeSpan.FromDays(10),
AccessPermissions.Read);
ILocator originLocator = _context.Locators.CreateSasLocator(myAsset, streamingPolicy, DateTime.UtcNow.AddMinutes(-500));
GetAssetSasUrlList(myAsset, originLocator);
string urlForClientStreaming = originLocator.Path + manifestFile.Name + "/manifest";
Console.WriteLine("URL to manifest for client streaming: ");
Console.WriteLine(urlForClientStreaming);
this url comes like --
https://mediasvc06w4dq5k8vd08.blob.core.windows.net/asset-064ed2d5-e42d-4c49-98eb-a712db5c614f?st=2012-12-26T23%3A04%3A22Z&se=2013-01-05T23%3A04%3A22Z&sr=c&si=9350bd2f-ec23-40b2-b27a-248bba01b97e&sig=oGgesnr8mXjCdTM5Dz%2FQpFRBDR0g0%2F60ECoXY14EvsA%3DBigBuckBunny.ism/manifest
Its not working .
When I paste this url on browser directly ,I get following error
AuthenticationFailedServer failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:154422cf-822e-4bbc-af2a-fa69273dfb89 Time:2012-12-27T08:57:30.9509847ZSignature fields not well formed.
But if I go and publish asset from portal( www.manage.windowsazure.com )--
I get like following url on protal..
http://mediaervices.origin.mediaservices.windows.net/5edbeae7-c3e6-45c5-bc5c-70f46b526cb5/BigBuckBunny.ism/Manifest
And it works with my silverlight player..
Now problem is that I am not getting url which starts with http from code and the url starting with https is not working with my player.
I guessed that its security issue and tried to host my player in winows azure and tried to player there but no success.
No, not a security issue. You are requesting a SAS url for a Smooth asset, you need an Origin URL. The correct code snippet is here, on my blog:
http://blog-ndrouin.azurewebsites.net/?p=1931
Specifically:
private static string GetStreamingUrl(CloudMediaContext context, string outputAssetId)
{
var daysForWhichStreamingUrlIsActive = 365;
var outputAsset = context.Assets.Where(a => a.Id == outputAssetId).FirstOrDefault();
var accessPolicy = context.AccessPolicies.Create(outputAsset.Name, TimeSpan.FromDays(daysForWhichStreamingUrlIsActive), AccessPermissions.Read | AccessPermissions.List);
var assetFiles = outputAsset.AssetFiles.ToList();
var assetFile = assetFiles.Where(f => f.Name.ToLower().EndsWith("m3u8-aapl.ism")).FirstOrDefault();
if (assetFile != null)
{
var locator = context.Locators.CreateLocator(LocatorType.OnDemandOrigin, outputAsset, accessPolicy);
Uri hlsUri = new Uri(locator.Path + assetFile.Name + "/manifest(format=m3u8-aapl)");
return hlsUri.ToString();
}
assetFile = assetFiles.Where(f => f.Name.ToLower().EndsWith(".ism")).FirstOrDefault();
if (assetFile != null)
{
var locator = context.Locators.CreateLocator(LocatorType.OnDemandOrigin, outputAsset, accessPolicy);
Uri smoothUri = new Uri(locator.Path + assetFile.Name + "/manifest");
return smoothUri.ToString();
}
assetFile = assetFiles.Where(f => f.Name.ToLower().EndsWith(".mp4")).FirstOrDefault();
if (assetFile != null)
{
var locator = context.Locators.CreateLocator(LocatorType.Sas, outputAsset, accessPolicy);
var mp4Uri = new UriBuilder(locator.Path);
mp4Uri.Path += "/" + assetFile.Name;
return mp4Uri.ToString();
}
return string.Empty;
}