Configuring use of AppIdentityService on development server - java

I have an app that currently uses the com.google.appendinge.api.appidentity.AppIdentityService to facilitate authentication & authorization for using the same app's [ie. same account] spreadsheet data via the SpreadsheetService API. Works great in production mode deployed to the GAE environment. But for obvious reasons, it doesn't work (authentication error, no surprise there) running in my development appengine environment.
My question is: is it possible & 'supported' to configure one's local development server to use the necessary key & certificate info to enable the AppIdentityService to work as intended?
I read the article https://sites.google.com/site/oauthgoog/authenticate-google-app-engine-app and I understand it to suggest that it is possible but I be mis-understanding key points & would appreciate any feedback pro & con regarding this.
In a perfect world, I'd like my testing env to mimic the production mode as closely as possible. I am also considering using the 'normal' oauth2 web app authentication in my testing env but would prefer sticking with using AppIdentityService if at all possible.
I suspect the com.google.appengine.api.appidentity.dev.LocalAppIdentityService class in the appengine-api-stubs.jar is the intended technique but has anyone else also used this to provide AppIdentityService authentication within a development server? My initial assumption is that replacing the class com.google.appengine.api.appidentity.IAppIdentityServiceFactoryProvider found in com.google.appengine.spi.FactoryProvider to use my own factory class using the above LocalAppIdentityService class. Or am I barking up the wrong tree?
Using GAE SDK 1.8.8 for Java.

When running under the local dev server, the GAE Java App Identity API calls the GoogleCredentials library to retrieve the default application credential.
The environment variable GOOGLE_APPLICATION_CREDENTIALS is checked. If this variable is specified it should point to a file that
defines the credentials. The simplest way to get a credential for this
purpose is to create a service account using the Google Developers
Console in the section APIs
& Auth, in the sub-section Credentials. Create a service account
or choose an existing one and select Generate new JSON key. Set
the environment variable to the path of the JSON file downloaded.
If you have installed the Google Cloud SDK on your machine and have run the command gcloud auth login, your identity can be used as
a proxy to test code calling APIs from that machine.
If you are running in Google App Engine production, the built-in service account associated with the application will be used.
If you are running in Google Compute Engine production, the built-in service account associated with the virtual machine instance
will be used.
If none of these conditions is true, an error will occur.
It looks like option #2 is probably easiest for you (run gcloud auth login to have your code use your Google account for authentication when run locally), but you could also do #1.

I have been working with GAE's PHP dev server and had the same issue with the AppIdentity service not working correctly. In PHP you can get around this by setting the $_SERVER['APPLICATION_ID'] to dev~yourapplicationid. I am sure there must be a way to do the same in Java, you just need to prepend dev~ to the start of your application ID to work with the dev environment.

Related

What is the preferred way to configure GCP credentials in Spring boot application

I am in process of writing a spring boot based microservice, which will be deployed on GKE. To configure service account credentials i do see there are multiple options available . What is the most preferred and possibly safer option available. I have tried below approaches, kindly suggest other ways
CredentialsProvider interface with spring.cloud.gcp.credentials.location
spring.cloud.gcp.credentials.encoded-key
GCP secrete manager
In Cloud environment generally the safest and best option with least administrative overhead is to use the corresponding service from the Cloud provider - in your case it would be Secret Manager. Of course if you are planning to not tie your applications with a specific cloud provider or cater to on-prem environment as well then you can use third party Secret management providers like HashiCorp Vault.
However even with Secret Manager if you interact with the API directly you will have to provide keys to call the API somewhere which creates another problem. The general recommended solution is to to use application authenticating as Service accounts and interacting with Secret manager directly as outlined here. Or there are alternative ways of mounting Secrets from Secret Manager on the GKE Volume using CSI Driver as explained here.
Running a secure cluster and container applications is a critical requirement and here are further recommendations for GKE security hardening which covers Secret management as well. More specifically you can check the recommendation in section "CIS GKE Benchmark Recommendation: 6.3.1"
Although #Shailendra gives you a good solution, as you are using GKE, you can store sensitive information as Kubernetes secrets.
Both the Kubernetes and GKE documentation provide several examples of creating secrets.
You can later use the configured secrets in multiple ways, in the simple use case, as environment variables that can be consumed in the application. Please, see as well this article.
Th Spring Cloud Kubernetes project provides support for consuming this secrets as property sources.
This approach allows you to test your application deployment locally, with minikube or kind, and later deploy the same artifacts to the cloud provider. In addition, it is cloud provider agnostic as you are using out-of-the-box Kubernetes artifacts.
I am afraid that we were so focused in provide you further alternatives that at the end we do not actually answer your question.
Previously, I will give you the advice of use Kubernetes Secrets, and it is still perfectly fine, but please, allow me to come back to it later.
According to the different properties you are trying setting, you are trying configuring the credentials on behalf your application with interact with other services deployed in GCP.
For that purpose the first thing you need is a service account.
In a nutshell, a service account is a software artifact that agglutinates several permissions.
This service account can be later assigned to a certain GCP resource, to a certain GCP service, and it will allow that resource to inherit or act on behalf of the configured permissions when interacting with other GCP resources and services.
Every service account will have an associated set of keys which identify the service account - the information you are trying to keep safe.
There are different types of service accounts, mainly, default service accounts, created by GCP when you enable or use some Google Cloud services - one for Compute Engine and one for App Engine - and user defined ones.
You can modify the permissions associated with these service accounts: the important thing to keep in mind is always follow the principle of least privilege, only grant the service account the necessary permissions for performing its task, nothing else.
By default, your GKE cluster will use the default Compute Engine service account and the scopes for it defined. These permissions will be inherited by your pods when contacting other services.
As a consequence, one possible option is just configuring an appropriate service account for GKE and use these permissions in your code.
You can use the default Compute Engine service account, but, as indicated in the GCP docs when describing how to harden the cluster security:
Each GKE node has an Identity and Access Management (IAM) Service Account associated with it. By default, nodes are given the Compute Engine default service account, which you can find by navigating to the IAM section of the Cloud Console. This account has broad access by default, making it useful to wide variety of applications, but it has more permissions than are required to run your Kubernetes Engine cluster. You should create and use a minimally privileged service account to run your GKE cluster instead of using the Compute Engine default service account.
So probably you will need to create a service account with the minimum permissions to run your cluster (and) application. The aforementioned link provides all the necessary information.
As an alternative, you can configure a different service account for your application and this is where, as a possible alternative, you can use Kubernetes Secrets.
Please:
Do not directly provide your own implementation of CredentialsProvider, I think it will not provide you any additional benefit compared with the rest of solutions.
If you want to use the spring.cloud.gcp.credentials.location configuration property, create a Kubernetes secret and expose it as a file, and set the value of this property to that file location.
In a very similar way, using Kubernetes Secrets, and as exemplified for instance in this article, you can expose the service account credentials under the environment variable GOOGLE_APPLICATION_CREDENTIALS, both Spring GCP and the different GCP client libraries will look for this variable in order to obtain the required credentials.
I would not use the configuration property spring.cloud.gcp.credentials.encoded-key, in my opinion this approach makes the key more suitable for threats - probably you have to deal with VCS problems, etc.
Secret Manager... as I told, it is a suitable solution as indicated by #Shailendra in his answer.
The options provided by Guillaume are very good as well.
The preferred way is hard to answer. Depends on your wishes...
Personally, I prefer to keep a high level of security, it's related to service account authentication and a breach can be a disaster.
Therefore, too keep the secrets secret, I prefer not having secrets. Neither in K8S secret nor in secret manager! Problem solved!!
You can achieve that with ADC (application default credential). But like that, out of the box, the ADC use the Node identity. The problem here is if you run several pods on the same node, all will have the same identity and thus the same permissions.
A cool feature is to use Workload Identity. It allows you to bind a service account with your K8S deployment. The ADC principle is the same, except that it's bind at the pods level and not at the node level (a proxy is created that intercept the ADC requests)
If your application is running on GCP the preferred way would be to use default credentials provided by the Google GCP clients. When using the default credentials provider the clients will use the service account that is associated with you application.

how do I pass on authentication tokens such as kerberos to Weblogic server through t3

I work on a project aiming to backport single-sign-on (SSO) to existing Weblogic/T3 based enterprise application. Ideally I would be able to utilize our Windows environment to perform this authentication using JAAS LoginContext and GSSAPI. This is unfortunately not documented for InitialContext provided by Weblogic (or at least I didn't find it yet) and it doesn't seem to have been explored by anyone else.
One idea is to authenticate to a Kerberos-realm (Microsoft Active Directory), pick the service ticket and pass it on through context environment. Custom IdentityAsserter is then required on the server side to extract and verify the service ticket.
Any ideas how to create and configure such IdentityAsserter? How to map the principal authenticated on a perimeter to application principal?
We have considered transforming the application to use http/https instead of t3/t3s but have no plans to follow that path, anticipating laborious tasks of redesign and associated test being somewhat out of the current project scope. As a consequence SPNEGO, servlet-filters, NegotiateIdentityAsserter and associated technologies will not provide us much help.

Google App Engine settings substitution for Dev vs Online

I am writing a Google App Engine (Java) application that reads data from a number of REST services, using OAuth for authentication. In order to support OAuth callbacks in my Development and Online environments, I have created 2 separate OAuth keys for the REST services - 1 that does a callback to 127.0.0.1 (development server) and 1 that does a callback to my real GAE website URL. This all works fine and happy.
Currently, to support this, I basically have a number of these statements throughout my code, anywhere that needs different values for Dev vs Online...
String devServer = request.getServerName();
if (devServer != null && devServer .equals("127.0.0.1")){
oauthKey = "<my_dev_key>";
}
else {
oauthKey = "<my_online_key>";
}
I was wondering whether GAE has any ability to auto-substitute different values for Development vs Online. I was thinking something like a 'settings' file that specifies 2 different values for a single setting, such that when the app is uploaded to GAE it replaces all setting references with the Online values. I would prefer that the values are substituted at upload-time rather than having a file sitting on the server with my Development settings in it, for security purposes.
Are there any alternatives that would be able to achieve a similar result without too much manual work every time I wish to upload a new version to GAE?
I would store the credential in different Properties files using something like Maven and its Profile feature to build an artifact for any specific environment.
Have a look to this project for the Google App Engine Maven plugin.

Can I run locally and debug a Web App that uses Google API's? [GWT+GAE]

I'm working on a web-app using Google App Engine with GWT, and I need to use Google API's (Google Calendar, Documents and so...).
As I know, I must configure a domain with Google to set my domain as callback of an OAuth Authentication. Am I right?
If so, am I forced to deploy on GAE to test? I mean, I can't run locally because my localhost can't be a valid callback.
Do you know any way to debug locally even using Google API's?
I have recommended to config a DynDNS, but isn't a solution in short term (incompatible router)...
If you use AuthSub instead I don't think you need to register a domain. The user just need a google account.
I have in the past used AuthSub together with Google Docs/Spreadsheet APIs on GAE and also been able to test it locally.
I can unfortunately not give you my code and exact solution (it was a while ago). But one of the samples I used extensively to base my code on was the FetcherServlet, check this code out:
http://code.google.com/p/google-app-engine-samples/source/browse/trunk/retrieving-gdata-feeds-java/src/com/google/appengine/demo/web/FetcherServlet.java?r=122
Also, I guess you might already have read this page (but their FetcherServlet uses OAuth, not AuthSub), so maybe just use it for some background info:
http://code.google.com/appengine/articles/java/retrieving_gdata_feeds.html

Java JEE5 App. Client with windows authentication and without prompting for user name and password

We have JAVA JEE5 enterprise application consisting of a web module and an app client running on glassfish.
We need to set authentication against active directory. I am aware that it is easy to set up LDAP based authentication for a web module or application client module but they are asking us to pick up the credentials from the windows logon when launching the application client and that somehow the credentials get propagated to the ejb tier as usual. This including not only the user principal but also the roles.
In brief, my question is: Can JAAS plug in to the windows authentication mechanism for desktop clients without prompting the user for user name and password?
Thanks,
Pablo.
I don't know about the details or JAAS compability but I believe that SPNEGO and/or Integrated Windows Authentication are the things you are looking for.
I haven't tried this, but here is a code example of pulling the NTLM username from the browser:
http://www.rgagnon.com/javadetails/java-0441.html
But, since you are talking about a desktop application your question may be how to get the username from within your java application, since NTLM really isn't involved.
http://www.roseindia.net/java/java-get-example/java-get-windows-username.shtml
Basically you would just use: System.getProperty("user.name").
UPDATE:
Since roles and all are needed, you may find that using JNI (http://download.oracle.com/javase/6/docs/technotes/guides/jni/) may be your best bet, but then you are tying this app to Windows, but it sounds like it will be anyway, as you can then call Windows API functions from Java.

Categories