Change nginx access log data in logstash or elasticsearch - nginx

In my project I provide api for a mobile app , and in every api the front end use session_id to mark user authenticity, and in the server side accept and validate it.
Recently we want to use ELK(elasticsearch, logstash, kibana) to preserve and analyze web server access log to extract some commonly occurred user activities. I encountered some problems, I wanna change session_id in the log to user_id(in program I can get user_id from session_id through query database) but I just don't know how?
Can logstash's filter do this? or should I change data when log was indexed in elasticsearch?

Alright, I try to give you an answer assuming that you have some kind of interface from which you can retrieve the user_id. Actually you need to do two things:
Split your log line into separate fields to have a field which contains your session_id
Get the corresponding user_id using some kind of api
Split your log line
You need to split your input into separate fields. This could be done with filters like grok and/or kv. Take a look at some SO questions to find a matching grok pattern or use the grok debugger. Please provide a few log lines if you need help with that.
EDIT: For your given examples your configuration should look something like this:
filter {
grok {
match => [ 'message', '"%{WORD:verb} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response} (?:%{NUMBER:bytes}|-) (?:"(?:%{URI:referrer}|-)"|%{QS:referrer}) %{QS:agent} %{QS:xforwardedfor}' ]
}
kv {
field_split => "&?"
}
}
Please try it and adjust it yourself to get the session_id.
Once you have a field called session_id you can go on with step 2.
Get the user_id
As you have already mentioned you need a filter plugin because the session_id must be available. There are several official plugins but I think none of them suits your purpose. Since the session_id is assigned dynamically you cannot use a static translate filter or something like that.
It depends on your api but one possible approach is to get the corresponding user_id via http requests. For that purpose you could use a community plugin. For example logstash-filter-rest with a config like this:
filter {
rest {
url => "http://yourserver/getUserBySessionId/"
sprintf => true
method => "post"
params => {
"session_id" => "%{session_id}"
}
response_key => "user_id"
}
}

Related

Exclude nextjs api url from sentry events

I have nextjs app with sentry. I want to add new api route, for example api/status, but I want to exclude it from being sent to sentry as it will clutter logs really fast and use my qouta.
I did a small research and it seems that there is an array of urls you can exclude from being tracked. It's called denyUrls. Read more. I have tried to add my url to this array, but it still tracks this url as part of events:
Sentry.init({
...
denyUrls: [
/api\/status/i,
],
...
});
Am I configuring something wrong or this array is not for the purpose of filtering everts.
If so, what's the best way to filter those? Other option I found which I will try next is beforeSend but it feels a bit overkill to simply exclude url. denyUrls feels like much better fit for what I am trying to achieve
I had the same issue and contacted the support for it. I am directly quoting the support here.
The BeforeSend and DenyUrl are options to filter error events, not transactions. For transaction events, please use the tracesSampler function as described on the page: https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/sampling/#setting-a-sampling-function.
Here is an example to drop all transactions that match a certain name:
tracesSampler: samplingContext => {
if(samplingContext.transactionContext.name == "GET /api/health"){
return 0.0 // never send transactions with name GET /api/health
}
return 0.2 // sampling for all other transactions
}
Note that you might need to customise the function above to better match your scenario.
I hope it will help you ;)
Have a nice day.

Telegram: How to find Group Chat ID?

I've been trying to solve this for three days and none pf the solutions I've found online seem to work, so I am going to have to ask for help.
I want to create a Telegram "Group Chat" to be used by members of a club I'm in. I created the chat named with the initials of the club, like: "ABCD" and added some members. Now I want to automate the sending of occasional messages to the group for all members to see. Weather forecast, random photograph from our gallery, etc.
Using #BotFather I created a bot called "ABCDbot" and noted the token for that bot. Now I have two "ABCD"s on my browser left side-panel. Selecting one gives me "ABCD bot" and selecting the other gives me "ABCD 123 members".
Using a perl script and LWP I can send a photo using
#!/usr/bin/perl -w
use feature 'say';
use LWP;
my $api = LWP::UserAgent->new ();
my $chat_id = '1234567890';
my $photo = '/home/user/gallery/photo999.jpg';
my $response = $api->post(
"https://api.telegram.org/bot<ABCDbot's token>/sendPhoto",
[ 'chat_id' => $chat_id,
'caption' => 'Photo Randomly Selected by the gallery',
'photo' => $photo,
],
'Content_Type' => 'form-data',
);
if ($response->is_success) {
say "Response..... Success!";
} else {
say "Response..... Failure!";
}
This works, providing I give it a legitimate chat_id and a legitimate file to send.
But the trouble is: I can't find the chat_id for the group chat with 123 members! Every method I've tried now proves to be obsolete or simply doesn't return the desired chat_id for the ABCD group chat. I can get my own chat ID or that of individual members of the group, or of the bot itself, and can successfully send photos, messages, etc to those destinations, but I just can't send anything to the group.
Can anybody walk me through the process of getting the chat_id for my group chat? Or direct me to a document describing an up-to-date, working method for obtaining same?
Assistance much appreciated.
Method 1 (WebZ)
This is based on JayeshRocks's question with some extra steps to make the ID work with Bot API. Thanks to him first.
Login to Telegram WebZ.
Open the chat you want to get its ID.
Your browser's address should look like https://web.telegram.org/z/#-1527776602.
Remove the protocol, domain and path keeping the anchor so your result looks like #-1527776602.
Replace "#-" with "-100" so it looks like -1001527776602.
You can now use your final result which should look like -1001527776602.
Method 2 (Private Supergroups)
If the chat is a private channel/supergroup, you can do the following:
Copy a link of a message. (It will look like https://t.me/c/1527776602/1002.)
Remove the protocol and domain name, so it looks like c/1527776602/1002.
Remove the first and last path, so it looks like 1527776602.
Append "-100" to the beginning of the result, so it looks like -1001527776602.
You can now use your final result which looks like -1001527776602.
Method 3 (Third-Party Bots)
If you trust 3rd party bots, there are many of them. A known one is #MissRose_bot which you can add it to your group and use its /id command. Another one is #usinfobot which works inline and only for public chats.
To get a telegram group ID you need to open the group on https://web.telegram.org/z/ when you do so click on the group you want to gain the ID of then if you look at the URL it will say something like https://web.telegram.org/z/#-1234567 and the numbers there is the ID of the telegram group!
Hope this helps

How to remove user id on url drupal 9

http://localhost/drupal-9.3.3/user/372#myaccount
How to remove user id on URL . Please suggest how to change these type security isssue.
If you want to change the url structure to remove ids, use pathauto https://www.drupal.org/project/pathauto
You can choose to have an url structure for user profiles that can be generated from any user field.
Someone told me that everything you write on the front end or in your main folder is always just basically a suggestion a.k.a. not secure.
Good ways to secure site:
Authenticate users using backend like firebase read/write permissions
Use randomized urls / keys (which firebase also does)
Also catch exceptions and deal with them, perferably at the the place where that function is created, not when it is executed:
Example
yes:
function() => {
// do something
//catch error
}
function(); // call function;
No:
function().then(error => { //do something})

How to store keywords in firebase firestore

My application use keywords extensively, everything is tagged with keywords, so whenever use wants to search data or add data I have to show keywords in auto complete box.
As of now I am storing keywords in another collection as below
export interface IKeyword {
Id:string;
Name:string;
CreatedBy:IUserMin;
CreatedOn:firestore.Timestamp;
}
export interface IUserMin {
UserId:string;
DisplayName:string;
}
export interface IKeywordMin {
Id:string;
Name:string;
}
My main document holds array of Keywords
export interface MainDocument{
Field1:string;
Field2:string;
........
other fields
........
Keywords:IKeywordMin[];
}
But problem is auto complete reads data frequently and my document reads quota increases very fast.
Is there a way to implement this without increasing reads for keyword ? Because keyword is not the real data we need to get.
Below is my query to get main documents
query = query.where("Keywords", "array-contains-any", keywords)
I use below query to get keywords in auto complete text box
query = query.orderBy("Name").startAt(searchTerm).endAt(searchTerm+ '\uf8ff').limit(20)
this query run many times when user types auto complete search which is causing more document reads
Does this answer your question
https://fireship.io/lessons/typeahead-autocomplete-with-firestore/
Though the receommended solution is to use 3rd party tool
https://firebase.google.com/docs/firestore/solutions/search
To reduce documents read:
A solution that come to my mind however I'm not sure if it's suitable for your use case is using Firestore caching feature. By default, firestore client will always try to reach the server to get the new changes on your documents and if it cannot reach the server, it will reach to the cached data on the client device. you can take advantage of this feature by using the cache first and reach the server only when you want. For web application, this feature is disabled by default and you can enable it like in
https://firebase.google.com/docs/firestore/manage-data/enable-offline
to help you understand this feature more check this article:
https://firebase.google.com/docs/firestore/manage-data/enable-offline
I found a solution, thought I would share here
Create a new collection named typeaheads in below format
export interface ITypeAHead {
Prefix:string;
CollectionName:string;
FieldName:string;
MatchingValues:ILookupItem[]
}
export interface ILookupItem {
Key:string;
Value:string;
}
depending on the minimum letters add either 2 or 3 letters to Prefix, and search based on the prefix, collection and field. so most probably you will end up with 2 or 3 document reads for on search.
Hope this helps someone else.

Creating a user failed. Is there a way to interogate the error?

I am using the ASP.NET Identity framework, with the EntityFramework provider (IdentityDbContext).
I attempt to create a user by calling UserManager.CreateAsync(..).
It returns an object of type IdentityResult, with the following values:
{
Succeeded: false,
Errors: ["Name AndrewShepherd is already taken."]
}
The error is valid - there is indeed another user called "AndrewShepherd" in the database. This is not a name the user picked; instead I am generating this name from the Outh2 account information provided by their Google account. (Google Accounts don't enforce unique names, just unique email addresses).
Since the problem is a duplicate name, I can simply try appending a number to the name and trying again. I would programmatically attempt to create AndrewShepherd_1, AndrewShepherd_2, AndrewShepherd_3 until I am either successful or get a different error.
But how do I programatically determine that the problem was a duplicate name?
Options are:
Perform a pattern match on the error string. This solution is guaranteed to break when the next version of ASP.NET Identity has a differently worded error messages or we internationalize the website.
Run the check before creating the user. I would call UserStore.FindByNameAsync to determine if the name had already been taken before invoking UserManager.CreateASync(..). This would have a small concurrency risk if two different sessions are attempting to add the same user name at the same time.
It would be some much easier if we could simply perform a check like this:
if(identityResult.Errors.Where(e => e.ErrorCode == IdentityErrors.DuplicateName).Any())
Is there a way I can perform a unique user check then add a user, that's safe in a concurrent environment?
As an alternaive, you can check if the user name is exist in your DB like that. If user name is already taken, you can change new user name like AndrewShepherd_1, AndrewShepherd_2, AndrewShepherd_3.
using (YourProjectName.Models.DefaultConnection db = new Models.DefaultConnection ())
{
if (db.AspNetUsers.Select(q => q.UserName).Contains("usernameThatYouWantToCheck"))
{
/*Your code*/
}
}

Resources