Pass Credentials to StorageOptions to Create Bucket - scala

I currently have a very simple function which creates a google storage bucket leveraging the Java API (in Scala). However, it currently infers gCloud credentials from the environment.
def createBucket(bucketName: String) = {
val storage = StorageOptions.getDefaultInstance.getService // May need to change. Creds inferred from environment.
val bucket = storage.create(BucketInfo.of(bucketName))
}
Is there any way to pass a GoogleCredential object into the constructor? Been stepping through the API # https://github.com/GoogleCloudPlatform/google-cloud-java/tree/master/google-cloud-storage/src/main/java/com/google/cloud/storage but haven't had any luck.

Found the answer outlined at https://github.com/GoogleCloudPlatform/google-cloud-java#authentication
Storage storage = StorageOptions.newBuilder()
.setCredentials(new GoogleCredentials(new AccessToken(accessToken, expirationTime)))
.build()
.getService();

Related

Is there yet an idiomatic way to make native calls to AWS Lambda or API Gateway from a Flutter application?

Goal: Make a signed request (SigV4) to AWS Lambda or API Gateway from a Flutter application (iOS, for the sake of this question).
For context, AWS introduced support for "native calls to AWS backends in [...] Flutter or Dart applications" back in May of 2022. There is an example of how to sign a request to Cognito to gather information about a User Pool, but I have not seen any application of this concept for Lambda or API Gateway calls, yet.
I'm wondering if anyone else has had success using AWS's official Dart packages to send signed requests or knows of another way to securely call AWS from a Flutter application.
EDIT:
I was able to accomplish the goal. Here's how I did it:
The code (all-caps denotes placeholders for your own values):
import 'dart:convert';
import 'package:aws_common/aws_common.dart';
import 'package:aws_signature_v4/aws_signature_v4.dart';
const signer = AWSSigV4Signer(
credentialsProvider: AWSCredentialsProvider.dartEnvironment(),
);
const region = 'REGION';
Future<void> yourFunction() async {
final scope = AWSCredentialScope(
region: region,
service: AWSService.apiGatewayV2,
dateTime: AWSDateTime(DateTime.now()),
);
final request = AWSHttpRequest(
method: AWSHttpMethod.post,
uri: Uri.https('HOST.execute-api.REGION.amazonaws.com','/STAGE_NAME'),
headers: const {
AWSHeaders.contentType: 'application/x-amz-json-1.1',
},
body: json.encode({
'EVENT_KEY':'EVENT_VALUE',
}).codeUnits,
);
final signedRequest = await signer.sign(
request,
credentialScope: scope,
);
final resp = await signedRequest.send();
final respBody = await resp.decodeBody();
print('\n\n${signedRequest.headers}\n\n${respBody}\n\n${resp.statusCode}\n\n');
}
Within a single AWS region (except where n/a):
create IAM user with execute-api:Invoke permission and programmatic access; store keys securely for later use.
create a Lambda function (can be the default, for testing).
create API in API Gateway:
REST (not private)
Regional endpoint
Add method (for me, POST)
IAM authorization type
Integration type is Lambda
select the target Lambda function, but
do not use Lambda proxy
deploy the newly created API to a new stage (give it a name)
Edit your dart file to include the new resources, including the stage name.
Test your API within API Gateway (I was getting 502 until I unchecked "Lambda proxy integration").
Run the following in your terminal after a successful API test; be sure to insert the keys for the IAM user you created.
flutter run --dart-define=AWS_ACCESS_KEY_ID=... --dart-define=AWS_SECRET_ACCESS_KEY=...
Summary:
In my case, I have a button that executes this function. If you keep the print statement in the above dart code, you should hopefully see {"statusCode": 200, "body": "\"Hello from Lambda!\""} as the response body.
Hope this helps others. Cannot make any guarantees that my approach will work in another environment. I also may have forgotten to include something relevant in the steps above. Still open to questions and suggestions.
Thank you.

How can I access a file of storage with dart Google Storage API

I'm trying to get information of a file that is inside of a folder in Google cloud Storage (not firebase storage). But the API of it in Dart language is not complete, it doesn't have a function to show the blob (file) information like we have in python same API. I just need to access the name of the file. Here's my code:
var credentials = auth.ServiceAccountCredentials.fromJson({
"type": "service_account",
...
});
List<String> scopes = []..addAll(Storage.SCOPES);
var client = await auth.clientViaServiceAccount(credentials, scopes);
var storage = Storage(client, "project_name");
var bucket = storage.bucket("Bucket_name");
var list = await bucket.read("folder_name/");
list.forEach((element) {
print(element.toString());
});
It has a lot of options like toList(),toSet(), asBroadcastStream() and etc. But any of these return me what I need. Some ones just return a empty list, that doesn't make sence for me.
Anyways, if someone know how to read data from a folder of GCP storage, please anwser me. Sorry for my english and Thanks!
The API docs: https://pub.dev/documentation/gcloud/latest/gcloud.storage/gcloud.storage-library.html
For you backend, you can use bucket.list(prefix: "folder_name/","") as described in the documentation:
Listing operates like a directory listing, despite the object namespace being flat. Unless delimiter is specified, the character / is being used to separate object names into directory components. To list objects recursively, the delimiter can be set to empty string.
For the front end, forget this! You can't provide a service account key file in your frontend! If you share the secret publicly, it's like if you set your bucket public!
So, for this, you need to have a backend that authenticated the user and generate a signed URL to read and write inside the bucket.
bucket.read() gets the contents of individual objects. If you want to get the object names, use bucket.list().

Intershop 7.10. - fetching payment configuration

We would like to fetch the payment configuration from Order in Java class (OrderBO extension). So far we have managed to fetch the service like this:
final OrderBOPaymentExtension<OrderBO> paymentExtension = getExtendedObject().getExtension(OrderBOPaymentExtension.EXTENSION_ID);
final PaymentBO paymentBO = paymentExtension.getPaymentBOs().stream().findFirst().orElse(null);
PaymentServiceBO paymentServiceBO = paymentBO.getPaymentServiceBO();
Now we need to fetch the configuration, so we can read certain configuration parameters from the payment method. What is the best way to do that?
We know it is possible to fetch the payment configuration through the PO Factory like this:
PaymentConfigurationPOFactory f = (PaymentConfigurationPOFactory)NamingMgr.getInstance().lookupFactory(PaymentConfigurationPO.class);
PaymentConfigurationPO r = f.getConfigForIDAndDomain(iD, domain);
But we would like to avoid using deprecated code.
UPDATE:
What we are trying to achieve is access these BO parameters in Java code:
I'd suggest you write a PaymentServiceBO extension. Within that extension you can write getter methods to query for certain config values. The java code for accessing service configuration object is:
PaymentConfiguration paymentConfig = paymentServiceBO.getExtension(PersistentObjectBOExtension.class).getPersistentObject();
ServiceConfigurationBO serviceConfigurationBO = repository.getServiceConfigurationBOByID(paymentConfig.getManagedServiceConfiguration().getUUID());
ConfigurationProvider configProviderExtension = serviceConfigurationBO.getExtension(ConfigurationProvider.class);
Configuration configuration = configProviderExtension.getConfiguration();
Logger.debug(this, "payment service config keys = {}", configuration.getKeys());
I believe PaymentConfiguration is deprecated. See PaymentConfigurationBO javadoc:
Deprecated since 7.6. Payment configurations are now represented via PaymentServiceBOs.
So you need to use PaymentServiceBO methods or write a business object extension that does what you want.

How to create a Blob from a Google Cloud Storage URL in Python

I have a blob created using the google cloud storage API, and have saved its path using blob.path. The path is of the form
/b/bucketname/o/some%2Fobject%2Fid
How do I recreate the blob from this URL?
It's unfortunate that the GCS API doesn't provide a factory method to go from the path URL back to a blob, since saving blob paths in databases etc. is quite common.
Here is a factory method that allows you to go from a blob.path back to a blob:
def blob_from_blobpath(blob_path):
import google.cloud.storage as gcs
blob_path = blob_path[3:] # /b/
slash_loc = blob_path.index('/')
bucket_name = blob_path[:slash_loc]
blob_name = blob_path[(slash_loc+3):] # /o/
bucket = gcs.Client().get_bucket(bucket_name)
return bucket.blob(blob_name)

Play Framework & JSON Web Token

Is there a Scala implementation of JWT or at least an example with Play? After having posted this question I searched further on the Internet and found some intros to JWT. Any suggestion would be really appreciated.
I am using Nimbus-JOSE-JWT in a spray.io app and am quite happy with it. The object performing authentication extends HttpAuthenticator and if it finds a correct JWT it returns the token subject and related info, otherwise None (authentication fails). With Play2 you can implement HTTP Basic Auth with something like this. Regarding token setting/getting which I assume is of more interest to you:
First, create a private/public key pair (I used parts of this code). Create the authentication object that loads the keys on initialization from the filesystem.
Create a a com.nimbusds.jose.crypto.MACSigner and a com.nimbusds.jose.crypto.MACVerifier using these keys.
Whenever you want to set a key, FIRST encrypt it, THEN sign it. Encryption:
private def encrypt(subject: String) = {
val header = new JWEHeader(JWEAlgorithm.RSA_OAEP, EncryptionMethod.A128GCM)
val jwt = new EncryptedJWT(header, claimSet(subject))
val encrypter = new RSAEncrypter(publicKey.asInstanceOf[java.security.interfaces.RSAPublicKey])
jwt.encrypt(encrypter)
jwt.serialize()
}
The claimSet method predictably returns a set of claims:
def claimSet(subject: String) = {
val jwtClaims = new JWTClaimsSet()
jwtClaims.setIssuer(Config.JWT.issuer)
jwtClaims.setSubject(subject)
jwtClaims.setJWTID(java.util.UUID.randomUUID().toString())
jwtClaims
}
The publicKey property is the value returned from KeyFactory.getInstance("RSA").generatePublic.
Signing:
private def sign(jwt: String) = {
val jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256), new Payload(jwt))
jwsObject.sign(Tokens.signer)
jwsObject.serialize
}
Given the above, when you receive a key you need to verify the signature first, then decrypt it. For verification, first you try to parse it with com.nimbusds.jose.JWSObject.parse(my_token) and as long as it doesn't throw a ParseException you call verify on the JWSObject that parse returns, using as an argument the MACVerifier that you created earlier. If verify returns true, you only need to call getPayload.toString on the same JWSObject to get the verified payload.
To decrypt the verified payload you call com.nimbusds.jwt.EncryptedJWT.parse on it, then something like:
val decrypter = new RSADecrypter(privateKey.asInstanceOf[java.security.interfaces.RSAPrivateKey])
jwt.decrypt(decrypter)
privateKey is the value returned from KeyFactory.getInstance("RSA").generatePrivate.
You can then get the claim set with jwt.getJWTClaimsSet.
Finally, with regard to setting the Authorization header, I'm doing this on my AngularJS client using principles also mentioned in this post.