How to set a specified engine ID for SNMP4J to send V3 trap - net-snmp

When I want to create a SNMPv3 user on the NMS, there need to input an engine ID which is an identifier string from SNMP Agent server for each user, so I input an casual id. For example:
createUser -e "0x80001370017f000101" "mytrapuser1" SHA "user1authpass" AES "user1encypass"
authUser log,execute,net mytrapuser1
And I can successfully send the trap from Agent server to NMS using below command:
snmptrap -v 3 -a SHA -A user1authpass -x AES -X user1encypass -l authPriv -u mytrapuser1 -e 0x80001370017f000101 {NMS-server-ip} 39 12.0.4.0
Now, everything looks ok.
But when I want to use java SNMP4j to send trap with the created user mytrapuser1 on Agent server, I don't know how to specify the request's engine id as 0x80001370017f000101, that caused the trap is sent failed on agent or the requested engine ID cannot be matched on the NMS.
My Questions:
1. Should I set a specified engine ID for SNMP4j to send a trap?
2. If #1 is not, how can I get an Agent server's engine id in advance, then I can use it to create user on NMS server?
3. If there are anything I understand wrong or use mistakes?
Is there anyone could help me, thanks very much.

Okay so lets see.
How I've seen it setup is the following:
The application creates an engine ID that it uses to send out traps. This engine ID corresponds with the application, and can be used as an identifier for your application.
So to answer question #1, I believe you should indeed set a specific engine id.
Which also answers question #2.
As for the workflow I believe it to be like this:
Your application is given an engine id.
The NMS creates a user with the engine id that you have defined in your application.
I would suggest making the engine id configurable, so that it can be changed easily without having to recompile the whole project.
Your application send a trap to the NMS, which will verify that the authentication, encryption and engine id match the user on the NMS.
The trap is processed on the NMS

OctetString uses a different string representation than NET-SNMP does. Thus, you need to specify your engine ID as follows
OctetString.fromString("8000000001020304", 16)
So you should basically do two things
snmp.getUSM().addUser(
new OctetString("username"),
OctetString.fromString("8000000001020304", 16),
new UsmUser(new OctetString("secname"), AuthSHA.ID, new OctetString("authphrase"),
PrivAES128.ID, new OctetString("privphrase"))
);
and
snmp.setLocalEngine(OctetString.fromString("8000000001020304", 16).getValue(), 0, 0);
your snmptrapd.conf should look like this
createUser -e 0x8000000001020304 username SHA authphrase AES privphrase
authUser log,execute,net username
snmpTrapdAddr udp:1166

Related

Limit the usage of Kerberos TGTs

I'm pretty new to Kerberos. I'm testing the Single Sign On feature using Kerberos. The environment: Windows clients (with Active Directory authentication) connecting to an Apache server running on Linux machine. The called cgi script (in Perl) connects to a DB server using the forwarded user TGT. Everything works fine (I have the principals, the keytab files, config files and the result from the DB server :) ). So, if as win_usr_a on Windows side I launch my CGI request, the CGI script connects to the remote DB and queries select user from dual and it gets back win_usr_a#EXAMPLE.COM.
I have only one issue I'd like to solve. Currently the credential cache stored as FILE:.... On the intermediate Apache server, the user running the Apache server gets the forwarded TGTs of all authenticated users (as it can see all the credential caches) and while the TGTs lifetime are not expired it can requests any service principals for those users.
I know that the hosts are considered as trusted in Kerberos by definition, but I would be happy if I could limit the usability of the forwarded TGTs. For example can I set the Active Directory to limit the forwarded TGT to be valid only to request a given service principal? And/Or is there a way to define the forwarded TGT to make it able to be used only once, namely after requesting any service principal, become invalid. Or is there a way the cgi script could detect if the forwarded TGT was used by someone else (maybe check a usage counter?).
Now I have only one solution. I can define the lifetime of the forwarded TGT to 2 sec and initiate a kdestroy in the CGI script after the DB connection is established (I set that the CGI script can be executed by the apache-user, but it cannot modify the code). Can I do a bit more?
The credential caches should be hidden somehow. I think defining the credential cache as API: would be nice, but this is only defined for Windows. On Linux maybe the KEYRING:process:name or MEMORY: could be a better solution as this is local to the current process and destroyed when the process is exited. As I know apache create a new process for a new connection, so this may work. Maybe KEYRING:thread:name is the solution? But - according to the thread-keyring(7) man page - it is not inherited by clone and cleared by execve sys call. So, if e.g. Perl is called by execve it will not get the credential cache. Maybe using mod_perl + KEYRING:thread:name?
Any idea would be appreciated! Thanks in advance!
The short answer is that Kerberos itself does not provide any mechanism to limit the scope of who can use it if the client happens to have all the necessary bits at a given point in time. Once you have a usable TGT, you have a usable TGT, and can do with it what you like. This is a fundamentally flawed design as far as security concerns go.
Windows refers to this as unconstrained delegation, and specifically has a solution for this through a Kerberos extension called [MS-SFU] which is more broadly referred to as Constrained Delegation.
The gist of the protocol is that you send a regular service ticket (without attached TGT) to the server (Apache) and the server is enlightened enough to know that it can exchange that service ticket to itself for a service ticket to a delegated server (DB) from Active Directory. The server then uses the new service ticket to authenticate to the DB, and the DB see's it's a service ticket for win_usr_a despite being sent by Apache.
The trick of course is that enlightenment bit. Without knowing more about the specifics of how the authentication is happening in your CGI, it's impossible to say whether whatever you're doing supports [MS-SFU].
Quoting a previous answer of mine (to a different question, focused on "race conditions" when updating the cache)
If multiple processes create tickets independently, then they have no
reason to use the same credentials cache. In the worst case they would
even use different principals, and the side effects would be...
interesting.
Solution: change the environment of each process so that KRB5CCNAME
points to a specific file -- and preferably, in an
application-specific directory.
If your focus in on securing the credentials, then go one step further and don't use a cache. Modify your client app so that it creates the TGT and service tickets on-the-fly and keeps it private.
Note that Java never publishes anything to the Kerberos cache; it may either read from the cache or bypass it altogether, depending on the JAAS config. Too bad the Java implementation of Kerberos is limited and rather brittle, cf. https://steveloughran.gitbooks.io/kerberos_and_hadoop/content/sections/jdk_versions.html and https://steveloughran.gitbooks.io/kerberos_and_hadoop/content/sections/jaas.html

How to protect web client ID in GCP source code

My GAE app publishes some APIs in GCP and uses the following structure:
# Replace the following lines with client IDs obtained from the APIs
# Console or Cloud Console.
WEB_CLIENT_ID = '????????????.apps.googleusercontent.com'
ALLOWED_CLIENT_IDS = [WEB_CLIENT_ID, endpoints.API_EXPLORER_CLIENT_ID]
SCOPES = [endpoints.EMAIL_SCOPE]
#endpoints.api(name=API_NAME,
version=API_VERSION,
description='An API to manage languages',
allowed_client_ids=ALLOWED_CLIENT_IDS,
scopes=SCOPES)
My doubt is if someone picks this source code from my machine or GitHub project. He or she can access the APIs using the discovered web client id.
What’s the best practice in this case?
I acknowledge that the client can expose the ID and someone have access to it. But I believe that is another matter.
There are many ways you can do this. One way is to always check in a default value for the client ID, so that when people check out your code, they have to modify it to deploy it. You can also move the client ID to its own module and not check it in at all, and make the expectation that they create their own module with their own client ID. This avoids having a modified state for a checked in file all of the time.
The client ID itself is not sufficient information to generate a valid token. The cryptography involved will prevent such a person from accessing your API.

SonarQube LDAP Authentication seems to load but won't allow login via domain user

I've been trying to setup SonarQube (v4.1) with the LDAP authentication plugin (v1.4) and I just can't get it to authenticate against my domain user. My config is setup as follows:
#########################
# LDAP configuration
#########################
# General Configuration
sonar.security.realm=LDAP
sonar.security.savePassword=true
sonar.security.updateUserAttributes=true
sonar.authenticator.downcase=true
sonar.authenticator.createUsers=true
ldap.authentication=simple
ldap.realm=mydomain.co.uk
ldap.bindDn=CN=USERNAME,OU=developers,DC=mydomain,DC=co,DC=uk
ldap.bindPassword=PASSWORD
# User Configuration
#ldap.user.baseDn=OU=developers,DC=mydomain,DC=co,DC=uk
ldap.user.request=(&(objectClass=user)(sAMAccountName={login}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail
# Group Configuration
ldap.group.baseDn=CN=Domain Users,CN=Users,DC=adastra,DC=co,DC=uk
ldap.group.request=(&(objectClass=group)(member={dn}))
and the log outputs the following messges that seem to say that the LDAP connection is working fine:
2014.01.20 16:12:32 INFO [org.sonar.INFO] Security realm: LDAP
2014.01.20 16:12:32 INFO [o.s.p.l.LdapSettingsManager] Auto discovery mode
2014.01.20 16:12:32 INFO [o.s.p.l.LdapSettingsManager] Detected server: ldap://dc02.mydomain.co.uk:389
2014.01.20 16:12:32 INFO [o.s.p.l.LdapSettingsManager] User mapping: LdapUserMapping{baseDn=dc=mydomain,dc=co,dc=uk, request=(&(objectClass=user)(sAMAccountName={0})), realNameAttribute=cn, emailAttribute=mail}
2014.01.20 16:12:32 INFO [o.s.p.l.LdapSettingsManager] Group mapping: LdapGroupMapping{baseDn=CN=Domain Users,CN=Users,DC=mydomain,DC=co,DC=uk, idAttribute=cn, requiredUserAttributes=[dn], request=(&(objectClass=group)(member={0}))}
2014.01.20 16:12:32 INFO [o.s.p.l.LdapContextFactory] Test LDAP connection on ldap://dc02.mydomain.co.uk:389: OK
2014.01.20 16:12:32 INFO [org.sonar.INFO] Security realm started
But it just doesn't seem to work for my user unless I use a local user. When enabling logging on the wrapper by setting:
wrapper.console.loglevel=DEBUG
I get the following error in the logs which doesn't really help that much! :)
2014.01.20 17:07:10 ERROR [rails] Error from external users provider:
I just worked through getting the SonarQube LDAP plugin to work with Active Directory myself. Since everyone's network is set up differently, you often can't just copy and paste a configuration. Here is the process I used to figure out the correct configuration at my company:
As stated in the documentation, this configuration goes in the file:
SONARQUBE_HOME/conf/sonar.properties
The following line is required as-is:sonar.security.realm=LDAP. Other lines will be different per company.
It was helpful for me to test the configuration with a GUI tool. I used the Softerra LDAP Browser (free read-only version of LDAP Administrator). In that LDAP Browser,
Create a new profile.
Lookup Servers button will help determine ldap.url. You will need to end up with something along the lines of ldap.url=ldap://dc01.mycompany.local:3268. NOTE: As stated in another answer, this may need to be a different port than the one listed in this screen.
The Base DN box can be left blank for now.
For authentication, I just chose the currently logged on user.
The filter can also be left blank for now.
Click Finish and it should display items at the top level of your AD.
F3 toggles the Quick Search bar.
Since you can't connect SonarQube to AD with Anonymous Authentication, you will need to select a user for the SonarQube service to connect as. Search for that user in the Quick Search.
You should find a CN (Common Name) entry. Double-click that to open it up.
Find the distinguishedName field and copy its value to use as your ldap.bindDn
ldap.bindPassword should be that user's password.
That should be enough to let SonarQube start successfully, but it is NOT enough to let it search for the user that is trying to log into your SonarQube web portal. For that, first pick a sample person (such as yourself).
Do another Quick Search for the sample person and open up their CN entry
Take the value of their distinguishedName, remove the "CN={Their Name}," piece, and put that into ldap.user.baseDn
The last piece that you need to determine with the ldap.user.request. The suggestion from the SonarQube docs to use with AD worked for me: (&(objectClass=user)(sAMAccountName={login})). Let me explain why, in case it does not work for you. The "{login}" will be replaced by whatever the SonarQube enters for their username, so that request string (which is called "Filter" in LDAP Browser) is essentially saying to search for all entries with any objectClass equal to "user" and their sAMAccountName equal to whatever is typed into the username textbox in your SonarQube web portal. Inside the sample person's info, there should be at least one field called "objectClass". One of those should have the value "user". There should also be an field for sAMAccountName. Use that value for the username textbox in your SonarQube web portal.
To test if that request string should work for you, do a Directory Search in LDAP Browser (Ctrl+F3). Put your ldap.user.baseDn value in the "Search DN" texbox and put your ldap.user.request value in the Filter texbox (be sure to manually replace "{login}" with your sample username). It should return the CN entry for the sample person.
Thanks to #aaron who managed to point me in the right direction! For my issue it was a problem with the auto-discovery and the forest I was connecting to. According to http://technet.microsoft.com/en-us/library/cc978012.aspx you should use a different port when connecting to a forest so that it can then search the whole forest rather that the domain you happen to connect to (which I suppose might not be the correct one in auto-discovery mode). In the end the configuration that worked for me was:
# General Configuration
ldap.realm=mydomain.com
sonar.security.realm=LDAP
sonar.authenticator.createUsers=true
sonar.security.savePassword=true
sonar.security.updateUserAttributes=true
ldap.url=ldap://dc.mydomain.com:3268
# User Configuration
ldap.user.request=(&(objectClass=user)(sAMAccountName={login}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail
Which is actually quite simple and doesn't require a user account to connect with. This means it is in SIMPLE authentication mode (I can't seem to get it to work in anything else) but that is fine with me as it's an internal only system.
I am using SonarQube 3.7.3 and I attached my configuration which works. I hope that would be useful.
# General Configuration
sonar.security.realm=LDAP
sonar.authenticator.createUsers=true
sonar.security.savePassword=true
sonar.security.updateUserAttributes=true
ldap.url=ldap://...
ldap.bindDn=user
ldap.bindPassword=password
# User Configuration
ldap.user.baseDn=ou=People,dc=company,dc=local
ldap.user.request=(&(objectClass=user)(sAMAccountName={login}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail
My Fix
I had painstakingly verified my settings, even to the point of using the log file's "User mapping" output line to configure a manual ldapsearch command and verify that my user was being retrieved properly.
For some reason, specifying this setting fixed it for me:
ldap.user.realNameAttribute=cn
Why?
This attribute is supposed to be optional and default to cn anyway, but it only works for me if I specify it manually. This might be a bug.
Debugging with ldapsearch
ldapsearch can allow you to bypass the application query LDAP directly.
I looked in the log file for this line:
INFO web[o.s.p.l.LdapSettingsManager] User mapping: LdapUserMapping{baseDn=DC=my-ad,DC=example,DC=com, request=(&(objectClass=user)(sAMAccountName={0})), realNameAttribute=cn, emailAttribute=mail}
And then built an ldapsearch command like:
ldapsearch -D CN=myldapuser,CN=Users,DC=my-ad,DC=example,DC=com -W -h my-ad.example.com -b "DC=my-ad,DC=example,DC=com" "(&(objectClass=user)(sAMAccountName=myuser))"
-D specifies the bind DN, basically the login username for LDAP
-W means that ldapsearch will prompt you for the password
-h specifies the LDAP URL
-b should be baseDN from the log file line
The last positional parameter is the request value from the log file line, after replacing {0} with a real username.
If you get real user info back, it means your basic settings are right. This is a hint that something else is going wrong.
http://blogs.msdn.com/b/visualstudioalm/archive/2015/11/13/support-for-active-directory-and-single-sign-on-sso-in-the-sonarqube-ldap-plugin.aspx
With the new v1.5, only one line is required:
LDAP configuration
sonar.security.realm=LDAP
Using port 3268 did the trick for me. Here is my configuration that works with SonarQube 5.0.1 and Active Directory:
sonar.security.realm=LDAP
sonar.security.savePassword=true
sonar.security.updateUserAttributes=true
sonar.authenticator.createUsers=true
ldap.url=ldap://dc101.office.company.com:3268
ldap.bindDn=CN=Service Account,OU=Windows Service,OU=Accounts,OU=Resources,DC=office,DC=company,DC=com
ldap.bindPassword=PASSWORD
ldap.user.baseDn=DC=office,DC=company,DC=com
ldap.user.request=(&(objectClass=user)(sAMAccountName={login}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail
None of solutions before worked for me, but this:
# Configuration
sonar.realm=myreal.domain.com
sonar.security.realm=LDAP
sonar.authenticator.createUsers=true
sonar.security.savePassword=true
sonar.security.updateUserAttributes=true
ldap.url=ldap://myreal.domain.com:389
ldap.bindDn=cn=CNUser,dc=domain,dc=com
ldap.bindPassword=password
# User Configuration
ldap.user.baseDn=ou=people,dc=domain,dc=com
ldap.user.request=(&(objectClass=user)(sAMAccountName={login}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail
#logeo lo que pasa
wrapper.console.loglevel=DEBUG
My Ldap server do needs authentication, so i cant avoid that. If it doesnt works for you, try not to especify the ldap.user.request: all depends of the configuration of your network´s LDAP server.

How to login with google account from client application into google app engine server?

Important: API has changed - Read this first:
https://developers.google.com/accounts/docs/AuthForInstalledApps
ClientLogin has been officially deprecated as of April 20, 2012. It
will continue to work as per our deprecation policy, but we encourage
you to migrate to OAuth 2.0 as soon as possible.
I want to build two application client (some python/java program) and server (Google App Engine application) and authenticated with google acount from client to server to get some secret information.
Let me explain scenario:
Server has address https://example.appspot.com.
Client want download restricted information from https://example.appspot.com/restricted so this url is defined and login: required in app.yaml.
Client use some Google Account example_login and example_password to get access.
How properly authenticate from client into Google App Engine to get access to https://example.appspot.com/restricted?
Another easy method, without login, is to use HMAC. You create a MAC signature based on timestamp (to make every request unique) and a secret MAC KEY. You request contains the timestamp and the MAC signature. The server can verify the MAC, because it also has the secret MAC KEY.
This Python code works on both sides (client and server)`:
import hmac, base64, hashlib
new_hmac = hmac.new(key=my_secret_MAC_KEY, msg=timestamp_in_request, digestmod=hashlib.sha256)
signature = base64.b64encode(new_hmac.digest()).decode()
if signature_in_request != signature : raise ValueError('access denied')
This works fine for a single user, because you have to manage a single key. When you have a lot of users, client login is a much better option.

Connecting to a webservice that requires a username, password and a .cer file using Axis2/C

--First a little background:--
I have already managed to connect to a Microsoft web service using C#. To use this web service, I have to supply a username and a password in the C# code. I also have to install a certificate (in .cer format) into the "Root Certificate Authorities" section of the system's certificates.
(By the way, the C# class I use to connect to the service was automatically generated for me with the command line tool "svcutil.exe https://address.of.service")
--Here is my question:--
How can I connect to this web service using Axis2/C? The example in the documentation is of a completely different nature -- it asks for a certificate, key file, and a passphrase. In my case, it is username, password, and a .cer file.
So I'm not sure where to even begin. I don't know where my .cer file, username and password should go exactly. Any ideas?
If at all possible stay away from Axis2, perhaps use gSOAP instead.
That said, figure out which of the HTTP libraries you are building Axis2 with (I believe it can use a number of different ones depending on which OS you are building etc).
Also you might want to update your question with the reference to the sample program you are talking about and relevant excerpt from the C# client for reference.

Resources