I am tring to connect to the the Object Storage service in Bluemix. However, I keep getting an exception. Here is my code:
public static void main(String[] args){
SwiftApi swiftApi;
String endpoint = "https://identity.open.softlayer.com/v2.0";
String tenantName = "object_storage_aedba606_1c69_4a54_b12c_2cecxxxxxx";
String userName = "e8ee36a1fa38432abcxxxxxxx";
String password = "Y6R(cY3xxxxxxxx";
String identity = tenantName+":"+userName;
String provider = "openstack-swift";
String region = "dallas";
Properties overrides=new Properties();
overrides.setProperty(Constants.PROPERTY_LOGGER_WIRE_LOG_SENSITIVE_INFO, "true");
swiftApi = ContextBuilder.newBuilder(provider)
.endpoint(endpoint)
.credentials(identity, password)
.overrides(overrides)
.buildApi(SwiftApi.class);
System.out.println("List Containers");
ContainerApi containerApi = swiftApi.getContainerApi(region);
Set<Container> containers = containerApi.list().toSet();
System.out.println("Listing Containers: ");
for (Container container : containers) {
System.out.println(" " + container);
}
System.out.println(" ");
}
I keep getting the following exception:
Exception in thread "main" org.jclouds.rest.AuthorizationException: request:
POST https://identity.open.softlayer.com/v2.0/tokens HTTP/1.1 [Sensitive data in payload,
use PROPERTY_LOGGER_WIRE_LOG_SENSITIVE_INFO override to enable logging this data.]
failed with response: HTTP/1.1 401 Unauthorized
at org.jclouds.openstack.swift.v1.handlers.SwiftErrorHandler.handleError
(SwiftErrorHandler.java:52)
at org.jclouds.http.handlers.DelegatingErrorHandler.handleError
(DelegatingErrorHandler.java:65)
at org.jclouds.http.internal.BaseHttpCommandExecutorService.shouldContinue
(BaseHttpCommandExecutorService.java:136)
My application is a standalone Java application. I am using the credentials that are supplied within my Object Storage service from Bluemix.
Any help is greatly appreciated.
This blog will help you connect to Object Storage in Bluemix https://developer.ibm.com/recipes/tutorials/connecting-to-ibm-object-storage-for-bluemix-with-java/
You can also access Object Storage using the Swift CLI https://console.ng.bluemix.net/docs/services/ObjectStorage/objectstorge_usingobjectstorage.html#using-swift-cli
Related
I'm studying the Vertx MongoClient API. I previously installed Restheart from Docker and it's own copy of mongodb, so now I have the default configuration for Restheart and the default configuration of Mongo in docker-compose.yml:
MONGO_INITDB_ROOT_USERNAME: restheart
MONGO_INITDB_ROOT_PASSWORD: R3ste4rt!
I put the Vertx Mongoclient into a Verticle:
public class MongoClientVerticle extends AbstractVerticle {
MongoClient mongoClient;
String db = "monica";
String collection = "sessions";
String uri = "mongodb://localhost:27017";
String username = "admin";
String password = "password";
MongoAuth authProvider;
#Override
public void start() throws Exception {
JsonObject config = Vertx.currentContext().config();
JsonObject mongoconfig = new JsonObject()
.put("connection_string", uri)
.put("db_name", db);
mongoClient = MongoClient.createShared(vertx, mongoconfig);
JsonObject authProperties = new JsonObject();
authProvider = MongoAuth.create(mongoClient, authProperties);
// authProvider.setHashAlgorithm(HashAlgorithm.SHA512);
JsonObject authInfo = new JsonObject()
.put("username", username)
.put("password", password);
authProvider.authenticate(authInfo, res -> {
if (res.succeeded()) {
User user = res.result();
System.out.println("User " + user.principal() + " is now authenticated");
} else {
res.cause().printStackTrace();
}
});
}
and I built a simple query:
public void find(int limit) {
JsonObject query = new JsonObject();
FindOptions options = new FindOptions();
options.setLimit(1000);
mongoClient.findWithOptions(collection, query, options, res -> {
if (res.succeeded()) {
List<JsonObject> result = res.result();
result.forEach(System.out::println);
} else {
res.cause().printStackTrace();
}
});
}
but when I access the db I get this error:
MongoQueryException: Query failed with error code 13 and error message 'there are no users authenticated' on server localhost:27017
What am I missing in the authentication process?
I'm using lastest restheart + mongodb and vertx 3.5.3
To be clear, RESTHeart doesn't come with its own copy of Mongodb but connects to any existing instance of Mongodb. The instance you can start via docker compose is for demo purposes only.
This question is much related to Vertx + Mongodb. I'm not an expert of it, but apparently Vert.x Auth Mongo does not use database accounts to authenticate users, it uses a specific collection (by default the "user" collection). You could double check the Vertx docs in case to be sure about this.
However, note that RESTHeart's main purpose is to provide direct HTTP access to Mongodb, without the need to program any specific client or driver. So the side point is that if you are using Vertx then you presumably don't need RESTHeart, and vice versa. Otherwise, you could simply connect to RESTHeart via Vertx's HTTP client, entirely skipping the MongoClient API.
Iam trying to authenticate a Java app with Cognito.
I have used for python the warrant library that worked very good. But i want to do the same in java now.
My Python function i used for authentication with the warrant library
def SRPauthentication(organizationAdmin,
password,
pool_id,
client_id,
client):
aws = AWSSRP(username=organizationAdmin,
password=password,
pool_id=pool_id,
client_id=client_id,
client=client)
tokens = aws.authenticate_user()
authorization_token= tokens['AuthenticationResult']['IdToken']
return authorization_token
with this i could easily acces some secured APIs.
Now i want to do the same with Java but i have problems.
This is my solution so far is this method:
public static void GetCreds()
{
AWSCognitoIdentityProvider identityProvider = AWSCognitoIdentityProviderClientBuilder.defaultClient();
AdminInitiateAuthRequest adminInitiateAuthRequest = new AdminInitiateAuthRequest().
withAuthFlow(AuthFlowType.USER_SRP_AUTH).
withClientId("234234234234").withUserPoolId("eu-central-1_sdfsdfdsf")
.addAuthParametersEntry("USERNAME", "UserK").
addAuthParametersEntry("PASSWORD","#######);
adminInitiateAuthRequest.getAuthFlow();
AdminInitiateAuthResult adminInitiateAuth = identityProvider.adminInitiateAuth(adminInitiateAuthRequest);
System.out.println(adminInitiateAuth.getAuthenticationResult().getIdToken());
}
When i run this i get an Exception:
Exception in thread "main" `com.amazonaws.services.cognitoidp.model.AWSCognitoIdentityProviderException: User: arn:aws:iam::XXXXXXXXXXXXXXXXX:user/khan is not authorized to perform: cognito-idp:AdminInitiateAuth on resource: arn:aws:cognito-idp:eu-central-1:XXXXXXXX:userpool/eu-central-1_XXXXXXX with an explicit deny (Service: AWSCognitoIdentityProvider; Status Code: 400; Error Code: AccessDeniedException; Request ID: 21be0b8e-adec-11e8-ad45-234234234)`
It says iam not authorized to perform this kind of instruction. So i guess iam doing something generally wrong. Because its working with my python code and in Java it recognizes my username from the credentials. The Cognito call should actually be independent from my aws credentials/useraccount right?
How to authenticate with Cognito using Java to get an Token to access secured aws services?
EDIT:
AWSCognitoIdentityProvider identityProvider = AWSCognitoIdentityProviderClientBuilder.standard()
.build();
InitiateAuthRequest adminInitiateAuthRequest = new InitiateAuthRequest()
.withAuthFlow(AuthFlowType.USER_SRP_AUTH)
.withClientId("XXXXXXXXXXXXXXXXX")
.addAuthParametersEntry("USERNAME", "user").
addAuthParametersEntry("PASSWORD","za$Lwn")
.addAuthParametersEntry("SRP_A",new AuthenticationHelper("eu-central-1XXXXXXXXX").getA().toString(16));
adminInitiateAuthRequest.getAuthFlow();
InitiateAuthResult adminInitiateAuth = identityProvider.initiateAuth(adminInitiateAuthRequest);
System.out.println(adminInitiateAuth);
I changed the AdminInitateAuthRequest to InitateAuthRequest. After that i had the Error missing SRP_A parameter that i somehow fixed with a similiar question here
And now i recive this :
{ChallengeName: PASSWORD_VERIFIER,ChallengeParameters: {SALT=877734234324234ed68300f39bc5b, SECRET_BLOCK=lrkwejrlewrjlewkjrewlrkjwerlewkjrewlrkjewrlkewjrlewkrjZ+Q==, USER_ID_FOR_SRP=user, USERNAME=user, SRP_B=43ecc1lwkerjwelrkjewlrjewrlkewjrpoipweoriwe9r873jr34h9r834hr3455f7d079d71e5012f1623ed54dd10b832792dafa3438cca3f59c0f462cbaee255d5b7c2werwerwerkjweorkjwerwerewrf5020e4f8b5452f3b89caef4a797456743602b80b5259261f90e52374adc06b456521a9026cce9c1cbe8b9ffd6040e8c1589d35546861422110ac7e38c1c93389b802a03e3e2e4a50e75d088275195f836f66e25f1a431dd56bb2},}
I have shorten the result with all the keys, but what to do next ?
Finally i could solve it with this code class.
There are multiple challenges involved in SRP authentication. The InitiateAuthRequest is one first request that is necessary.
This similiar question helped me :
stackoverflow
stackoverfow
String PerformSRPAuthentication(String username, String password) {
String authresult = null;
InitiateAuthRequest initiateAuthRequest = initiateUserSrpAuthRequest(username);
try {
AnonymousAWSCredentials awsCreds = new AnonymousAWSCredentials();
AWSCognitoIdentityProvider cognitoIdentityProvider = AWSCognitoIdentityProviderClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.withRegion(Regions.fromName(this.region))
.build();
InitiateAuthResult initiateAuthResult = cognitoIdentityProvider.initiateAuth(initiateAuthRequest);
if (ChallengeNameType.PASSWORD_VERIFIER.toString().equals(initiateAuthResult.getChallengeName())) {
RespondToAuthChallengeRequest challengeRequest = userSrpAuthRequest(initiateAuthResult, password);
RespondToAuthChallengeResult result = cognitoIdentityProvider.respondToAuthChallenge(challengeRequest);
//System.out.println(result);
System.out.println(CognitoJWTParser.getPayload(result.getAuthenticationResult().getIdToken()));
authresult = result.getAuthenticationResult().getIdToken();
}
} catch (final Exception ex) {
System.out.println("Exception" + ex);
}
return authresult;
}
private InitiateAuthRequest initiateUserSrpAuthRequest(String username) {
InitiateAuthRequest initiateAuthRequest = new InitiateAuthRequest();
initiateAuthRequest.setAuthFlow(AuthFlowType.USER_SRP_AUTH);
initiateAuthRequest.setClientId(this.clientId);
//Only to be used if the pool contains the secret key.
//initiateAuthRequest.addAuthParametersEntry("SECRET_HASH", this.calculateSecretHash(this.clientId,this.secretKey,username));
initiateAuthRequest.addAuthParametersEntry("USERNAME", username);
initiateAuthRequest.addAuthParametersEntry("SRP_A", this.getA().toString(16));
return initiateAuthRequest;
}
I am developing a web project with HSQLDB persistence. My database instance is on server mode, therefore, I need to run a cmd script/ Java method to access my schema.
Tomcat is the container I use to drop my war on port 8080. Gradle is my build system.
Currently I am using the following main method before I deploy my app to properly access my database on runtime:
public static void main(String[] args) throws IOException, ServerAcl.AclFormatException {
final String URL = "file:~/db/cursago";
String user = "user";
String password = "password";
HsqlProperties p = new HsqlProperties();
p.setProperty("server.database.0",URL+";user="+user+";password="+password);
p.setProperty("server.dbname.0","cursago");
Server server = new Server();
server.setProperties(p);
server.setLogWriter(null);
server.setErrWriter(null);
server.start();
System.out.println("Database is running with path: " + URL);
System.out.println("Username: " + user+", Password: " + password);
}
I would like to know if there's a way of making Tomcat/Gradle/IntelliJ IDEA run this main method before a project deploy, instead of running this script by hand.
from here:
you could run the content of your main in the onApplicationEvent like:
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
final String URL = "file:~/db/cursago";
String user = "user";
String password = "password";
HsqlProperties p = new HsqlProperties();
p.setProperty("server.database.0",URL+";user="+user+";password="+password);
p.setProperty("server.dbname.0","cursago");
Server server = new Server();
server.setProperties(p);
server.setLogWriter(null);
server.setErrWriter(null);
server.start();
System.out.println("Database is running with path: " + URL);
System.out.println("Username: " + user+", Password: " + password);
}
}
This will trigger on every event, that could be application started or redeployed and happens before your application handles requests.
You also can wire in your properties.
There are some difficulties if the server is already running and it can't run in this scope only.
when i run this code
public class test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String podName = "xrdpprocan";
String namespace = "default";
String master = "https://my_ip_adress";
Config config = new ConfigBuilder().withMasterUrl(master).withTrustCerts(true).build();
try (final KubernetesClient client = new DefaultKubernetesClient(config)) {
String log = client.pods().inNamespace(namespace).withName(podName).getLog(true);
System.out.println("Log of pod " + podName + " in " + namespace + " is:");
System.out.println("------------------");
System.out.println(log);
} catch (KubernetesClientException e) {
System.out.println(e.getMessage());
}
}
i get this Error reading service account token from: [/var/run/secrets/kubernetes.io/serviceaccount/token]. Ignoring.
Where is the problem: The current type of your client configuration is incomplete, you are missing the client authentication settings/data part.
Please be aware, when you are running your code from outside the cluster
(this type of client configuration is called out-of-cluster client configuration) you need to specify explicitly a bare minimum for successful connection to Kubernetes control-plane from outside.
Kubernetes Master URL
At least one method for user authentication, can be any of:
client certificates
bearer tokens
HTTP basic auth
You see the problem ? - you have specified none of these from the second condition for >> user << authentication (this is a key word here: user)
Right now Java Kubernetes client falls back into Service account based authentication strategy, thinking you are not human but robot (Pod running in context of Service Account).
Putting it technically, client is resolving now to the last resort option:
KUBERNETES_AUTH_TRYSERVICEACCOUNT
(4th on the list of fabric8io/kubernetes-client supported configuration option, check below)
which involves reading in service account token placed into the filesystem inside Pod's container at following path:
/var/run/secrets/kubernetes.io/serviceaccount/token
Officially fabric8io/kubernetes-client java client supports the following ways of configuring the client:
This will use settings from different sources in the following order
of priority:
System properties
Environment variables
Kube config file
Service account token & mounted CA certificate <== you client code tries this
System properties are preferred over environment variables. The
following system properties & environment variables can be used for
configuration
The easiest solution is to rely on Kube config file option to access cluster from outside, e.g.:
public class KubeConfigFileClientExample {
public static void main(String[] args) throws IOException, ApiException {
// file path to your KubeConfig
String kubeConfigPath = System.getenv("HOME") + "/.kube/config";
// loading the out-of-cluster config, a kubeconfig from file-system
ApiClient client =
ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
// set the global default api-client to the in-cluster one from above
Configuration.setDefaultApiClient(client);
// the CoreV1Api loads default api-client from global configuration.
CoreV1Api api = new CoreV1Api();
// invokes the CoreV1Api client
V1PodList list =
api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null, null);
for (V1Pod item : list.getItems()) {
System.out.println(item.getMetadata().getName());
}
}
}
Full code sample can be found here.
I'm using amazon SDK 1.5.6 and trying to initialize the connection using a proxy server.
The initialization succeed, but when I try to use the AmazonEC2Client it fails with the following
error:
Caught Exception: Status Code: 407, AWS Service: AmazonEC2, AWS
Request ID: null, AWS Error Code: 407 Unauthorized, AWS Error Message:
Unable to unmarshall error response (Premature end of file.) Reponse
Status Code: 407 Error Code: 407 Unauthorized Request ID: null
Initialization code:
protected AmazonEC2 initAmazonSDKClient(String endpoint) {
AWSCredentials awsCredentials =
new BasicAWSCredentials(_account.getAccessKey(), _account.getSecretKey());
ClientConfiguration config = getProxySettings();
AmazonEC2 ret = CloudServicesEC2Api.getAmazonEC2Client(awsCredentials, config);
ret.setEndpoint(endpoint);
_endPointToAmazonEC2Client.put(endpoint, ret);
return ret;
}
private ClientConfiguration getProxySettings() {
ClientConfiguration ret = new ClientConfiguration();
String host = _proxySettings.getServer();
if (!StringUtils.isNullOrEmpty(host )) {
ret.setProxyHost(host );
}
if (!StringUtils.isNullOrEmpty(_proxySettings.getPort())) {
ret.setProxyPort(Integer.valueOf(_proxySettings.getPort()));
}
String proxyUserName = _proxySettings.getUserName();
if (!StringUtils.isNullOrEmpty(proxyUserName)) {
ret.setProxyUsername(proxyUserName);
}
String proxyPassword = _proxySettings.getPassword();
if (!StringUtils.isNullOrEmpty(proxyPassword)) {
ret.setProxyPassword(proxyPassword);
}
ret.setProxyWorkstation(host );
ret.setProxyDomain(host );
return ret;
}
Code that uses the client and causes the error:
private List<InstanceStatus> getStatusChecks(AmazonEC2 ec2Client, String[] hostIds) {
DescribeInstanceStatusRequest describeInstanceRequest =
new DescribeInstanceStatusRequest().withInstanceIds(hostIds);
DescribeInstanceStatusResult describeInstanceResult =
ec2Client.describeInstanceStatus(describeInstanceRequest);
return describeInstanceResult.getInstanceStatuses();
}
I know the root cause is the NTLM authentication, I need to somehow configure the NTLM host & NTLM domain, in my code sample its the lines:
ret.setProxyWorkstation(host );
ret.setProxyDomain(host );
I have tried several versions of workstation & domain, i tried leaving it blank, no use...
Please advise!
Well, after some research it turns out that something is not right in the way Amazon SDK handles NTLM proxy requests. We've compared the proxy parameters passed to other libraries (e.g JClouds) where the connection succeeded and tried applying the same on Amazon SDK with no luck.
We have even compared the packets using wireshark, everything is the same. Something is just not right with this library...