How to specify public-read policy on a complete bucket in aws? - android

I have a bucket named foo inside which resides my two subfolders named bar and foobar.
Hierarchy
foo
-bar
-foobar
Problem
Now i want to make my uploaded objects public readable. Using xhr (by allowing CORS) i was able to do so. But using AWS android sdk the public-read acl is still not implemented in their api as specified by this feature request on GITHUB
So as evident i am not able to make my uploaded objects using AWS Android sdk
So please help me in solving this issue.

This can be done via S3 bucket policy. See Bucket Policy Examples. It looks like what you need is to allow anonymous read to objects under a bucket. You can apply the following bucket policy to the bucket foo.
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AddPerm",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::foo/bar/*","arn:aws:s3:::foo/foobar/*"]
}
]
}
This should also answer the question on Github.

The transfer manager currently does not support ACL; however, you can use AmazonS3Client to perform putObject(). You can take a look at the AWS Mobile SDK for Android API Reference for more details.

Related

Creating enrollment token gives back wrong QR code

I'm trying to provision a device with QR code method according to these documentations.
I'm using this Google collab quickstart guide to do so.
Right now, I'm stuck here:
enrollment_token = androidmanagement.enterprises().enrollmentTokens().create(
parent=enterprise_name,
body={
"policyName": policy_name,
"qrCode": "{'android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME': 'com.tmp.app.admin/.AdminReceiver','android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM': 'MUQ6NEQ6MDQ6NTY6M0E6ODA6Mzg6NEY6NUM6ODI6Qzk6NUY6MkM6QjA6RTk6RDc6QTM6RjI6NDg6NTA6QTQ6RjY6QTA6RjM6MTA6NUM6MzI6NkY6QkU6NUI6M0E6Qzk%3D','android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION':'https://myurl-stuff.com/link_part/my_app.apk','android.app.extra.PROVISIONING_SKIP_ENCRYPTION': false,'android.app.extra.PROVISIONING_WIFI_SSID': 'MY_WIFI_SSID','android.app.extra.PROVISIONING_WIFI_PASSWORD': 'my_wifi_password','android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE': 'WPA'}"
}
).execute()
json.dumps(enrollment_token, indent=2)
Whenever I run this code, the output is the following.
{\n "name": "enterprises/LC00y54m79/enrollmentTokens/UV4yLfxoyWSln7CArwtp7OJQiHH_Gvc76JttPa4-r48",\n "value": "ZBNWPOWHBQUPNLMBTNRU",\n "expirationTimestamp": "2023-02-06T12:43:34.634467Z",\n "policyName": "enterprises/LC00y54m79/policies/policy1",\n "qrCode": "{\\"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME\\":\\"com.google.android.apps.work.clouddpc/.receivers.CloudDeviceAdminReceiver\\",\\"android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM\\":\\"I5YvS0O5hXY46mb01BlRjq4oJJGs2kuUcHvVkAPEXlg\\",\\"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION\\":\\"https://play.google.com/managed/downloadManagingApp?identifier=setup\\",\\"android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE\\":{\\"com.google.android.apps.work.clouddpc.EXTRA_ENROLLMENT_TOKEN\\":\\"ZBNWPOWHBQUPNLMBTNRU\\"}}"\n}
It is the default Google example and it does not contains my application, instead, it contains Google's official example app.
What am I doing here wrong?
EDIT:
I have syntax error with double quotes.
EDIT 2:
Also tried with starting and ending single quotes like:
'{"android.app.extra (...)
Also tried with starting and ending with triple quotes like in Google's previous example like here:
But still no luck.
The api either returns a syntax error or simple doesn't returns with my app/parameters in the qrCode, instead it replaces to their own example project.
EDIT 3:
Tried like this:
But with no success:
There are two ways to manage devices :
Provision a device with your own DPC : Your DPC is installed (referenced by an URL in the QR code). It fetches policies from your servers and applies them as a profile / device owner, without using any Google API (Android only).
Manage devices using Google Play EMM API. It is basically Google's layer on top of the Android API (but often called Android Management API, which is a bit confusing) : Your EMM console send policies to Google's servers. They are applied on the devices by Google's own DPC.
You are trying to mix the two approaches. It is no longer possible :
Android Enterprise is no longer accepting new registrations for custom device policy controllers (DPC) using the Google Play EMM API.
All new EMM solutions should now use Android Management API, which comes with its own DPC provided by Google.
The Google DPC is the com.google.android.apps.work.clouddpc you are seeing in the generated QR code.
If you want to use you own DPC, you need to use the json containing the android.app.extra.PROVISIONING* keys directly, without wrapping it in a Google token.
The content looks fine except the SSID has to be quoted, and the signature hash should not be percent encoded :
{
"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME": "com.tmp.app.admin/.AdminReceiver",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION": "https://myurl-stuff.com/link_part/my_app.apk",
"android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM": "MUQ6NEQ6MDQ6NTY6M0E6ODA6Mzg6NEY6NUM6ODI6Qzk6NUY6MkM6QjA6RTk6RDc6QTM6RjI6NDg6NTA6QTQ6RjY6QTA6RjM6MTA6NUM6MzI6NkY6QkU6NUI6M0E6Qzk=",
"android.app.extra.PROVISIONING_SKIP_ENCRYPTION": false,
"android.app.extra.PROVISIONING_WIFI_PASSWORD": "my_wifi_password",
"android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE": "WPA",
"android.app.extra.PROVISIONING_WIFI_SSID": "\"MY_WIFI_SSID\""
}
You just have to generate a QR code containing this content (with any generator), and scan it with the device.
Unfortunately the provisioning process is not forgiving. If something is wrong, the device shows a "Provisionning failed" error message without any clue. You have to triple check everything.

Amazon IAP Android onProductDataResponse always fails

I am trying to implement a simple subscription IAP on Android using the Amazon SDK. I adjusted their subscription sample app. The code is really simple.
Set <String>productSkus = new HashSet<String>();
productSkus.add("TLS_SKU_MONTHLY" );
productSkus.add( "TLS_SKU" );
PurchasingService.getProductData(productSkus);
But the response from onProductDataResponse() is always fail. I'm not sure why, I cannot find any examples etc to even know if my SKUs are right, in the sample app they looked more like package names than this, but these strings are what I entered on the 'in-app items' on the apps page on Amazon. The app has not been submitted yet, but I need to test and implement IAP before that. Any ideas? I cannot even find a simple tutorial walking through this, and as usual their docs are poor.
edit, noticed im getting these errors that dont even come up on google
Kiwi: DataAuthenticationKeyLoaderV3: Unable to load authentication Key
java.io.FileNotFoundException: AppstoreAuthenticationKey.pem
DATA_AUTH_KEY_LOAD_FAILURE: CERT_NOT_FOUND: null
com.amazon.a.a.o.b.a.a: DATA_AUTH_KEY_LOAD_FAILURE: CERT_NOT_FOUND: null
I'm wondering, is this because I am running on real Android and not an Amazon device like a fire tablet or tv stick?
You should add your own AppstoreAuthenticationKey.pem to the project assets folder. It is not (and should not be) delivered together with the sample.
Basically, you must do a few things:
Login to the Amazon developer console and create your application.
Go to the “Apk Files" tab to download AppstoreAuthenticationKey.pem.
Add this file to the project’s assets folder.
You can get the full instructions from Amazon.
As for devices, yes, you must use an Amazon device. But this should not be the reason why you are getting this exception.

Upload files from android app to my S3 bucket

I'm pretty confused about what method should I use. OK here's what I'm actually trying to do:
User registers with my app need to upload multiple files/images
These files/images need to be uploaded to my s3 bucket
Uploading these files using presigned URL seems to be out of the question since I need to upload multiple files/images and it seems presigned URL is only good for a single file.1
I then look at AWS SDK for Java 2.0, and this seems what I need; however, when I read the [setup credentials][1] I become confused because:
It seems this will use the credentials setup in our OS environment. So how will my app use these credentials later when it's installed in other users' devices?
I have multiple AWS credentials profile in my OS. I'm still unclear on how to actually load my credentials profile, as it's not the default profile
So upon further reading the link, it seems supply credentials explicitly with
AwsSessionCredentials awsCreds = AwsSessionCredentials.create(
"your_access_key_id_here",
"your_secret_key_id_here",
"your_session_token_here");
should fit me the best. But if I put my access_key_id, secret_key_id in my app's strings.xml file, wouldn't it be a security issue?
1 FYI I have successfully implemented upload single image using presigned URL for another activity. I use retrofit which connects to my lambda function which then returns the presigned URL, and made another retrofit PUT request to the presigned URL

Android SDK for fingerprint matching - External device

I'm developing an Android application that uses U.are.U 4500 fingerprint reader to identify users. I already have a backend server, that uses SQL Server, to store and register user data and now I need my app to be able to read the user fingerprint and verify if this fingerprint matches any of the fingerprints on the database. Does anyone know a SDK that is able to do this comparison?
I'm using asia.kanopi.fingerscan package to read the user fingerprint and I already have the scan working, now I only need to get this image and compare to the data on the SQL database. I saw a few answers here on StackOverflow telling me to use openCV library for Android, but none of them could give me any lead on how to do it.
I based my development on this tutorial: https://medium.com/touch4it/fingerprint-external-scanner-with-usb-database-sdk-64c3ec5ea82d, but unfortunately I couldn't find the SDK IDKit Fingerprint SDK Mobile anywhere.
How can I sucessufully match the image with the one stored on the database?
For those who are still looking for an answer to this problem. It's been a while since I actually implemented my solution and, when I did it, I added this line to my app gradle file:
com.github.lmone:SourceAFIS-Android:v3.4.0-fix3
But now I can't seem to find the github link anywhere. Maybe the repository got deleted. If someone find it, please send it to me so I can update my answer here.
Besides that, if you can still add the library to your Android project, the basic idea is to use a FingerprintMatcher to compare two FingerprintTemplate.
Example:
FingerprintTemplate probe = new FingerprintTemplate().dpi(500).create(digital_byte_array);
while (result.next()) {
byte[] imgCandidate = digital_to_compare;
FingerprintTemplate candidate = new FingerprintTemplate()
.dpi(500)
.create(imgCandidate);
double score = new FingerprintMatcher()
.index(probe)
.match(candidate);
if (score >= 40) {
// Found a match
}
}
In my case, I found the performance a little slow. It was usable, but nothing compared to Android's built-in fingerprint device. Also, the bigger your digitals collection, the longer it will take to find a match.
The score of the match is up for you to decide what suits better your project. 40 was a reliable amount in my case. The same goes to the FingerprintTemplate dpi.
Also, the method .create() receives a byte[] as parameter.
EDIT
I found this link and I'm almost certain it is the library I used, but under a new repository name:
https://github.com/robertvazan/sourceafis-java
The docs looks just the same as the code I used: https://sourceafis.machinezoo.com/java
To match a user on server side, you have to use an AFIS server : https://en.wikipedia.org/wiki/Integrated_Automated_Fingerprint_Identification_System
Here some providers of AFIS solution:
http://www.neurotechnology.com/megamatcher.html
https://www.nec.com.au/expertise/safety-security/identity-access/fingerprint
https://www.innovatrics.com/innovatrics-abis/
https://www.dermalog.com/products/software/civil-afis-abis/
http://www.m2sys.com/automated-fingerprint-identification-system-afis/

Publish a Android private app for multiple clients

What we are dealing with
We have this app which we distribute to our clients in an offline fashion (i.e. not uploaded to Play store). The app flavour distributed to each client is almost identical with a bit of tweak here and there. All our clients share this app to their employees for usage. Basically this is an Enterprise App.
What's the problem
Recently one of our client started using a MDM (Mobility Device management) tool which blocks apps which are not downloaded from Google play. As obviously we got a request from our client to see if we can upload this app on Google play or not.
Important thing here is that we have over 100 clients and the package name of the app provided to each client is actually the same. So it's the same app with a bit of tweak here and there. If we go down the road of publishing the app to the play store, we might end up in a mayhem (we don't wanna upload 100 different apps to the play store - i.e. one for each client). We are doing some optimisation from our end so that multiple clients can use the same app (but we can't make all 100+ clients use the same app.).
What am I looking at ?
I started looking at Android For Work (AFW), Google private apps , Managed Google play and still digesting the stuffs. But to me it looked like just a secure way for enterprises to deploy/publish apps which can be downloaded only on specific devices and under a certain profile (which keeps things separate from user's personal apps and data in case they use the same phone for personal and work purpose).
What solution i am looking for ?
To privately deploy an app (host it with Google or privately host
but listed with Google play in both cases) and let my clients share
this app with their employee.
Each private app for each client should be on its own little
private island. I want to distribute the app with the same package
name to all my clients (From what I have read so far, this might not
be possible with Google play. But I am hoping somebody can point out
facts if I am missing something).
This is my solution:
Creating run-time dynamic app that get data and configs from back-end and render its views and data with its own Client Id.
You can create single app and upload to google play, but you should manage your clients by clientId that makes every app acts separated. This clientId is unique and generated per your clients. This solution have two sides. Android side and server side.
1 - Android side: Our app should have a baseUrl like this in Constants:
baseUrl = "http://yourCorporation.com/{clienId}/api/"
And then all the services of All clients use the same url. clientId is the key point. The difference of you client app is clientId. For generating url of api-call you should do something like this:
Constant.ClientId = scannedQRCode;
url = baseUrl.replace("{client_id}",Contant.ClientId) + apiUrl ;
You must create QR code per your clients that should scanned in app first run. It is good to send QR code after registration to his/her (client of your Clients) email. This QR code have clientId. Therefor every clients have their own services and really works as separated islands, even if you want to change server address, you can put all baseUrl in QR code but this is not suggested, because you have to create server per clients and this is headache.
You can even handle config and UI elements of you app with calling a config api that returns a customConfigDto as json like this:
public class CustomConfigDto {
String colorPrimary ;
String colroPrimaryDark ;
String colorAccent ;
int tabCounts;
//and more...
public String getColorPrimary() {
return colorPrimary;
}
public void setColorPrimary(String colorPrimary) {
this.colorPrimary = colorPrimary;
}
public String getColroPrimaryDark() {
return colroPrimaryDark;
}
public void setColroPrimaryDark(String colroPrimaryDark) {
this.colroPrimaryDark = colroPrimaryDark;
}
public String getColorAccent() {
return colorAccent;
}
public void setColorAccent(String colorAccent) {
this.colorAccent = colorAccent;
}
public int getTabCounts() {
return tabCounts;
}
public void setTabCounts(int tabCounts) {
this.tabCounts = tabCounts;
}
}
And render your views by this configurations. All of this works separated per app by their clientId.
I prefer QR code because it is very handy and classy and fit in your case, however you can enter this clientId with many other ways. This is one of best free and simple QR code generating service, and this is one of best QR-code scanner library for android.
2 - Server Side: You have to handle step1 in server-side and it is very easy. You can have entity calls Client that all other entities have it. Because you should keep all of your data in one place but separated by your clients. You can also map APIs like this in Spring:
#RequestMapping(value = "http://yourCorporation.com/{clienId}/api/customers", method = RequestMethod.GET)
Customers getCustomers(#PathVariable("clienId") Long clientId) {
return customerService.findCustomerByClientId(clientId);
}
Based on what you've said, this sounds more like you can solve this with configuration management than sending each client completely separate APKs.
Google has a private channel, but based on the documentation it seems much more oriented towards having a single membership list (i.e. once you're granted access you have access to the entire private channel) rather than highly customized access (i.e. certain people have access to certain items in the channel).
An alternative that I suggest: have all clients download the same APK. Give each of them a client-specific "activation code" for your app. When the app starts for the first time, it calls a web service and passes it its activation code; on the server side, you use the Activation Code to identify the client and then return data on the correct configuration to the client. Then you can distribute the same APK to everyone on your private channel and configure it remotely once it's installed.
A major advantage of this scheme is that you can have multiple configurations for an organization. Just give the client a choice of several activation codes, each of which will give them a certain configuration. For example, if you have an app that's used by both dock workers and janitors (and I'm just throwing out an example here), you could give the dock workers one activation code and janitors a second activation code and you can then easily give them different configurations.
Google Play now allows a developer to publish an app privately to up to 20 Managed Play organizations (or enterprises). To do so (instructions copied from the help center):
Sign in to the Google Play Console.
Go to Pricing & Distribution > User programs > Managed Google Play.
Check the Turn on advanced managed Google Play features box.
Check the Privately target this app to a list of organizations box.
Click Choose Organizations.
For each organization that you want to publish the app to, enter the Organization ID and a description (or name) and click Add. You can enter up to 20 organizations per app.
The good, long solution:
don't use the same package name for different apps. Create a multimodule project, set one module for the core, shared stuff, and add a module for each client where you can tweak what you need and configurate the package name dynamically based on build type. That way you can use the same package name for your CI server and everything else and have another package name when releasing the app.
The short workaround that may work:
Publish the app as a closed google play beta, and send invitations only to this client. That way he can distribute the app to his employees through play store and the other clients won't notice I can't assure it will work not knowing which MDM tool you are facing, but since beta channel apps don't require unknow origins permissions, you should be fine.
If you want the same package name, you'll have to do something like what EJoshuaS suggested: manage the different configurations inside of one app version. You won't be able to have more than one app with the same package deployed on Google Play.
If you're open to having different packages, you could just change the package name in the Android Manifest for each one and release as a different app. You would need to change the package everywhere you import the R file and you would need to make sure that all class references in your Manifest include the entire class path (<activity android:name="[full.package].MainActivity"> rather than <activity android:name=".MainActivity">). This gets pretty confusing and is terrible in terms of configuration management, so it's not really a great solution in general, but it might work for you.
I started looking at Android For Work (AFW), Google private apps , Managed Google play and still digesting the stuffs.
This would probably be a good fit for AFW.
But to me it looked like just a secure way for enterprises to deploy/publish apps which can be downloaded only on specific devices and under a certain profile
That's what an MDM does, yes, but there's more to it. With Android for Work you also have Managed Configurations which let you pass in a configuration for the app. This can be used to change backend urls, etc.
It for sure supports your second requirement, but I know too little to be certain about the first. While you can privately host and rollout an app on Google Play for Work, I don't know about distributing it privately to multiple clients.
The obvious benefit of using this Google API is that you don't have to build anything yourself. Also most MDMs support those Android for Work APIs, so that a domain admin can buy the app in bulk and distribute them to the employees. Have a look at the AppConfig Community which shows MDM Providers that incorporated those APIs and best practices.
Whatever you decide, you should definitely have a good look at Android for Work as what you are describing is exactly what it is intended for. The initial setup is a pain and there is way too little information about how it all works and plays together, but spending a few days trying to figure it out might be better than just building your own managed solution which you then will have to maintain too.

Categories

Resources