Can't connect to GRPC server which is deployed on AWS ECS - amazon-web-services

I have a GRPC server written on C#.
internal class Program
{
internal static void Main(string[] args)
{
using (var waitHandle = new AutoResetEvent(false))
{
void OnConsoleOnCancelKeyPress(object o, ConsoleCancelEventArgs e)
{
e.Cancel = true;
// ReSharper disable once AccessToDisposedClosure
waitHandle.Set();
}
Console.CancelKeyPress += OnConsoleOnCancelKeyPress;
var config = new AppConfig(new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false)
.Build());
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule(new Module());
containerBuilder.RegisterModule(new Data.Module(config.Region, config.TablePrefix));
using (var container = containerBuilder.Build())
{
var buyRatesService = container.Resolve<BuyRatesService>();
var logger = container.Resolve<ILogger<Program>>();
var server = new Server
{
Services =
{
BuyRates.BindService(buyRatesService)
},
Ports = {new ServerPort("0.0.0.0", 50051, ServerCredentials.Insecure)}
};
try
{
server.Start();
logger.LogDebug("Service started");
waitHandle.WaitOne();
}
catch (Exception e)
{
logger.LogCritical("Application terminated unexpectedly. Exception {#exception}", e);
}
finally
{
server.ShutdownAsync().Wait();
Console.CancelKeyPress -= OnConsoleOnCancelKeyPress;
}
}
}
}
}
It works fine locally. I deploy it to ecs instance(Docker). The container port is 50051. ALB and Route 53 are used.
When I'm trying to connect to someroute54uri.net:50051 I get an error
Grpc.Core.RpcException: Status(StatusCode=Unavailable, Detail="Connect Failed").
In case when I'm trying to connect to someroute54uri.net, I get an error
Grpc.Core.RpcException: Status(StatusCode=Unavailable, Detail="Trying to connect an http1.x server").
Thanks!.
Please, let me know if additional information helps to solve the issue.

Related

AddSingleton won't accept AddSerilog

I'm facing an issue where I'm trying to write a more smart console app with logging and configuration available.
This is what I have so far:
namespace Client
{
public class Program
{
public static IConfigurationRoot Configuration;
private static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(Serilog.Events.LogEventLevel.Debug)
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.CreateLogger();
try
{
MainAsync(args).ConfigureAwait(false);
return 0;
}
catch
{
return 1;
}
}
private static async Task MainAsync(string[] args)
{
// Create service collection
Log.Information("Creating service collection");
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
// Create service provider
Log.Information("Building service provider");
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
try
{
Log.Information("Starting service");
await serviceProvider.GetService<App>().Run();
Log.Information("Ending service");
}
catch (Exception ex)
{
Log.Fatal(ex, "Error running service");
throw;
}
finally
{
Log.CloseAndFlush();
}
}
private static void ConfigureServices(IServiceCollection services)
{
// Add logging
services.AddSingleton(
LoggerFactory.Create(
builder => { builder.AddSerilog(dispose: true); }));
services.AddLogging();
// Build configuration
Configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
.AddJsonFile("appSettings.json", false)
.Build();
// Add access to generic IConfigurationRoot
services.AddSingleton(Configuration);
// Add app
services.AddTransient<App>();
}
}
}
I'm facing an issue in ConfigureServices method on line builder.AddSerilog for the life of me, I cannot figure out why it is not able to resolve AddSerilog
I was missing a package: Serilog.Extensions.Logging
For some reason, VS or even Resharper was not able to suggest this.

Use KCL 1.* in Lambda: Credentials

Using the examples provided in https://github.com/aws/aws-sdk-java/tree/master/src/samples/AmazonKinesis I understand how to use the KCL to read KinesisEvents from my local machine.
I am trying to implement the same logic in Lambda Functions.
To set up the KinesisClientLibConfiguration, you need to provide an AWSCredentialsProvider.
Where do I get these AWSCredentials to create the kinesisClientLibConfiguration in a Lambda?
KinesisClientLibConfiguration kinesisClientLibConfiguration = new KinesisClientLibConfiguration(SAMPLE_APPLICATION_NAME, SAMPLE_APPLICATION_STREAM_NAME, credentialsProvider, workerId);
The full code of the handler looks like this:
public class ProcessKinesisRecords implements RequestHandler<KinesisEvent, Void> {
public static final String SAMPLE_APPLICATION_STREAM_NAME = "kinesis-s";
public static final String SAMPLE_APPLICATION_STREAM_REGION = "eu-west-1";
private static final String SAMPLE_APPLICATION_NAME = "SampleKinesisLambdaApplication";
private static final InitialPositionInStream SAMPLE_APPLICATION_INITIAL_POSITION_IN_STREAM =
InitialPositionInStream.LATEST;
private static ProfileCredentialsProvider credentialsProvider;
public Void handleRequest(KinesisEvent event, Context context) {
init();
int exitCode = 0;
try {
String workerId = InetAddress.getLocalHost().getCanonicalHostName() + ":" + UUID.randomUUID();
KinesisClientLibConfiguration kinesisClientLibConfiguration =
new KinesisClientLibConfiguration(SAMPLE_APPLICATION_NAME,
SAMPLE_APPLICATION_STREAM_NAME,
credentialsProvider,
workerId);
kinesisClientLibConfiguration.withInitialPositionInStream(SAMPLE_APPLICATION_INITIAL_POSITION_IN_STREAM);
kinesisClientLibConfiguration.withRegionName(SAMPLE_APPLICATION_STREAM_REGION);
IRecordProcessorFactory recordProcessorFactory = new AmazonKinesisApplicationRecordProcessorFactory();
Worker worker = new Worker(recordProcessorFactory, kinesisClientLibConfiguration);
System.out.printf("Running %s to process stream %s as worker %s...\n",
SAMPLE_APPLICATION_NAME,
SAMPLE_APPLICATION_STREAM_NAME,
workerId);
worker.run();
} catch (Throwable e) {
System.err.println("Caught throwable while processing data.");
e.printStackTrace();
}
System.exit(exitCode);
return null;
}
private static void init() {
// Ensure the JVM will refresh the cached IP values of AWS resources (e.g. service endpoints).
java.security.Security.setProperty("networkaddress.cache.ttl", "60");
credentialsProvider = new ProfileCredentialsProvider();
try {
credentialsProvider.getCredentials();
} catch (Exception e) {
throw new AmazonClientException("Cannot load the credentials", e);
}
}
}
Lambda does provide environment variables for the credentials:
https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html#lambda-environment-variables
Access them via the EnvironmentVariableCredentialsProvider:
https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/auth/EnvironmentVariableCredentialsProvider.java

DataSource connections pool

I have a data source configured with its connections pool ready to use, and it is exposed to my application via JDNI, but the code my colleagues wrote actually opens and closes a connection for every query. How does WSO2 handle this? Does it really close the connection given by the pool, or it ignores the close and just considers this connection free to be added back to the pool and ready to be used by any other client?
Connection conn = null;
CallableStatement cStmt = null;
try {
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put("java.naming.factory.initial", "org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory");
Context initContext = new InitialContext(environment);
DataSource ds = (DataSource) initContext.lookup("jdbc/tvaccount");
if (ds != null) {
conn = ds.getConnection();
cStmt = conn.prepareCall("{call getAccountStatusAttr(?)}");
cStmt.setString("pUserLogin", userName);
cStmt.execute();
}
} catch (Exception e) {
log.error("Exception while getting account status: ", e);
} finally {
if (cStmt != null) {
try {
cStmt.close();
} catch (SQLException e) {
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
Have you added this java code as a JAR file in WSO2 ESB and then accessed the method by using class mediator? if this is the case then it behaves like a normal java code wherein once the query is executed the connection will be closed.

Auth0 OWIN API not validating JWT token when published via Docker Container on AWS EC2

My OWIN Web.API 2 Hosted on EC2 will not authorize a JWT token. I have tested the functionality locally with out a problem but once I publish it out to my docker container hosted on EC2 it responds with a 401. I am using the default RS256 Algorithm and these settings:
var domain = Environment.GetEnvironmentVariable("AUTH0_DOMAIN");
var audience = Environment.GetEnvironmentVariable("AUTH0_CLIENT_IDS");
var keyResolver = new OpenIdConnectSigningKeyResolver(domain);
appBuilder.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = audience,
ValidIssuer = domain,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) => keyResolver.GetSigningKey(identifier)
}
});
My Endpoint simply states whether your are authenticated or not.
[Authorize]
[Route("secure")]
public HttpResponseMessage GetSecured()
{
var userId = ClaimsPrincipal.Current.Identity.GetUserId();
return Request.CreateResponse($"Hello, {userId}! You are currently authenticated.");
}
Here is my Startup config:
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.UseCors(CorsOptions.AllowAll); //must be first
Auth0Config.Register(appBuilder);
var httpConfiguration = new HttpConfiguration();
httpConfiguration.MapHttpAttributeRoutes();
UnityConfig.Register(httpConfiguration);
appBuilder.UseWebApi(httpConfiguration);
}
I no longer use the OWIN pipeline but from a previous project here is how I had it configured. It looks like you are using OpenID, I did not. Not sure if this helps.
var issuer = AppSettings.Auth0Domain;
var audience = AppSettings.Auth0ClientID;
var secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["Auth0ClientSecret"]);
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] {audience},
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
},
Provider = new Auth0AuthenticationProvider()
});
EDIT Added Auth0AuthenticationProvider
public class Auth0AuthenticationProvider : IOAuthBearerAuthenticationProvider
{
private string token;
public Task ApplyChallenge(OAuthChallengeContext context)
{
return Task.FromResult<object>(null);
}
public Task RequestToken(OAuthRequestTokenContext context)
{
token = context.Token;
return Task.FromResult<object>(null);
}
public Task ValidateIdentity(OAuthValidateIdentityContext context)
{
if (string.IsNullOrEmpty(token))
return Task.FromResult<object>(null);
var notPadded = token.Split('.')[1];
var padded = notPadded.PadRight(notPadded.Length + (4 - notPadded.Length % 4) % 4, '=');
var urlUnescaped = padded.Replace('-', '+').Replace('_', '/');
var claimsPart = Convert.FromBase64String(urlUnescaped);
var obj = JObject.Parse(Encoding.UTF8.GetString(claimsPart, 0, claimsPart.Length));
// simple, not handling specific types, arrays, etc.
foreach (var prop in obj.Properties().AsJEnumerable())
{
switch (prop.Name)
{
case "app_metadata":
SetAppMetadataClaims(context, prop.Value.ToString());
break;
}
}
return Task.FromResult<object>(null);
}
private static void SetAppMetadataClaims(OAuthValidateIdentityContext context, string jsonString)
{
var appMetadata = JsonConvert.DeserializeObject<Auth0AppMetaDataModel>(jsonString);
if(!context.Ticket.Identity.HasClaim("AccountId", appMetadata.accountId.ToString()))
context.Ticket.Identity.AddClaim(new Claim("AccountId", appMetadata.accountId.ToString()));
if (!context.Ticket.Identity.HasClaim("ClientId", appMetadata.clientId.ToString()))
context.Ticket.Identity.AddClaim(new Claim("ClientId", appMetadata.clientId.ToString()));
if (!context.Ticket.Identity.HasClaim("IsActive", appMetadata.isActive.ToString()))
context.Ticket.Identity.AddClaim(new Claim("IsActive", appMetadata.isActive.ToString()));
if (appMetadata.roles == null)
return;
foreach (var role in appMetadata.roles)
{
if (context.Ticket.Identity.HasClaim(ClaimTypes.Role, role))
continue;
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.Role, role));
}
}
}
The problem was not with Auth0 using HS256 or RS256 but instead with the base image I was using. Mono was failing silently most likely blocking the validation of my token. I have switched over to dotnet core in order to use the docker image: microsoft/dotnet:latest
My Startup file now appears like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors("CorsPolicy");
var options = new JwtBearerOptions
{
Audience = Configuration["Auth0:ApiIdentifier"],
Authority = $"https://{Configuration["Auth0:Domain"]}/"
};
app.UseJwtBearerAuthentication(options);
...
}

uploading file from backberry to web service = JVM error 104 Uncaught NullPointerException?

I am developing a small blackberry project.
Here are the step that it is supposed to be:
User clicks Speak! button. The application record speech voice. [No Problem]
When user finishes speaking, click Stop! button. Once the stop button is clicked, the speech voice will be saved on BB as an AMR file. Then, the file will be sent to web service via ksoap2. Web service will return response as a string of file name. The problem is web service return nothing and there is an error occur: JVM error 104: Uncaught NullPointerException I wonder if I placed the code on the right place, or I did something wrong with ksoap2??
here is the code for web service
namespace VoiceServer
{
/// <summary>
/// Converting AMR to WAV
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
public string UploadFile(String receivedByte, String location, String fileName)
{
String filepath = fileName;
/*don't worry about receivedByte and location, I will work on them after the problem is solved :) */
return "Success"+filepath;
}
private void InitializeComponent()
{
}
}
}
Below is the code running on Eclipse, I'm not sure if I placed the code for sending file to web service on the right place.
public class MyAudio extends MainScreen {
private ButtonField _startRecordingButton;
private ButtonField _stopRecordingButton;
private HorizontalFieldManager _fieldManagerButtons;
private VoiceNotesRecorderThread _voiceRecorder;
private LabelField _myAudioTextField;
private DateField hourMin;
private long _initTime;
public MyAudio() {
_startRecordingButton = new ButtonField("Speak!", ButtonField.CONSUME_CLICK);
_stopRecordingButton = new ButtonField("Stop!", ButtonField.CONSUME_CLICK);
_fieldManagerButtons = new HorizontalFieldManager();
_voiceRecorder = new VoiceNotesRecorderThread(500000,"file:///store/home/user/voicefile.amr",this);
_voiceRecorder.start();
myButtonFieldChangeListener buttonFieldChangeListener = new myButtonFieldChangeListener();
_startRecordingButton.setChangeListener(buttonFieldChangeListener);
_stopRecordingButton.setChangeListener(buttonFieldChangeListener);
_fieldManagerButtons.add(_startRecordingButton);
_fieldManagerButtons.add(_stopRecordingButton);
_myAudioTextField = new LabelField(" Welcome to VoiceSMS!!!" );
add(_fieldManagerButtons);
add(_myAudioTextField);
SimpleDateFormat sdF = new SimpleDateFormat("ss");
hourMin = new DateField("", 0, sdF);
hourMin.setEditable(false);
hourMin.select(false);
_initTime = System.currentTimeMillis();
add(hourMin);
}
public void setAudioTextField(String text) {
_myAudioTextField.setText(text);
}
public void startTime() {
_initTime = System.currentTimeMillis();
hourMin.setDate(0);
}
public void updateTime() {
hourMin.setDate((System.currentTimeMillis()-_initTime));
}
class myButtonFieldChangeListener implements FieldChangeListener{
public void fieldChanged(Field field, int context) {
if(field == _startRecordingButton) {
try {
_voiceRecorder.startRecording();
} catch (IOException e) {
e.printStackTrace();
}
}else if(field == _stopRecordingButton) {
_voiceRecorder.stopRecording();
//----------Send AMR to Web Service-------------//
Object response = null;
String URL = "http://http://localhost:portnumber/Service1.asmx";
String method = "UploadFile";
String NameSpace = "http://tempuri.org/";
FileConnection fc = null;
byte [] ary = null;
try
{
fc = (FileConnection)Connector.open("file:///store/home/user/voicefile.amr",Connector.READ_WRITE);
int size = (int) fc.fileSize();
//String a = Integer.toString(size);
//Dialog.alert(a);
ary = new byte[size];
fc.openDataInputStream().read(ary);
fc.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
SoapObject client = new SoapObject(NameSpace,method);
client.addProperty("receivedByte",new SoapPrimitive(SoapEnvelope.ENC,"base64",Base64.encode(ary)));
client.addProperty("location","Test/");
client.addProperty("fileName","file:///store/home/user/voicefile.amr");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = client;
HttpTransport http = new HttpTransport(URL);
try
{
http.call(method,envelope);
}
catch(InterruptedIOException io)
{
io.printStackTrace();
}
catch (IOException e)
{
System.err.println(e);
}
catch (XmlPullParserException e)
{
System.err.println(e);
}
catch(OutOfMemoryError e)
{
System.out.println(e.getMessage());
}
catch(Exception e)
{
e.printStackTrace();
}
try
{
response = envelope.getResponse();
Dialog.alert(response.toString());
}
catch (SoapFault e)
{
System.err.println(e);
System.out.println("Soap Fault");
}
catch(NullPointerException ne)
{
System.err.println(ne);
}
Dialog.alert(response.toString());
//Dialog.alert("Send Success");
//----------End of Upload-to-Web-Service--------//
}
}
}
}
I don't know if the file is not sent to web service, or web service has got the file and produce no response??? I am a real newbie for BB programming. Please let me know if I did anything wrong.
Thanks in advance!!!
There is a typo in your URL variable value.
"http://" typed twice
String URL = "http://http://localhost:portnumber/Service1.asmx";
Hooray!!! Problem Solved!
just changed URL as Rafael suggested and added [WebMethod] above "public string UploadFile" in the web service code