Tuesday 21 August 2018

AWS Rekognition Text detection limited to 50 words

AWS Rekognition Text detection limited to 50 words


Feb 2022 - this post is permanently moved to https://architectfwd.com, my new site, and can be found here  - https://architectfwd.com/architecture/cloud/amazon-web-services-aws/rekognition/2022/01/23/aws-rekognition-text-detection-limited/ please go and bookmark that site for all of my future content.



I built an API which uses Rekognition on AWS quickly, just to test the text detection capability.

Approach 

I create a Flask API and utilised boto.

rek = boto3.client('rekognition', region_name="us-east-1")

After that I took the image bytes directly and ran a detect_text call, not too tough.

Detect text result


I uploaded an image with a small number of words and was pleased with the result. However when uploading an image containing a paragraph I found that only a subset of the words were returned.

The limit is 50 words - "DetectText can detect up to 50 words in an image."[0]

Text result response


The response splits up items by Type, either "line" or "word", and has a parentID when a word, so I filtered just the lines like this:

if label['Type']=="LINE"

It works, great result, but a solution for a larger number of words makes me think of just running this through Tesseract OCR.

[0] - https://docs.aws.amazon.com/rekognition/latest/dg/text-detection.html (Last paragraph)

Cheers
Quintes


Connect with me on LinkedIn or Twitter

Saturday 21 April 2018

AWS Lambda function created via cloudformation doesn't log

AWS Lambda function created via cloudformation doesn't log


Feb 2022 - this post is permanently moved to https://architectfwd.com, my new site, and can be found here  - https://architectfwd.com/architecture/cloud/amazon-web-services-aws/lambda/2022/01/23/aws-lambda-function-created-via-cloudformation-doesnt-log/ please go and bookmark that site for all of my future content.


I provisioned new lambda functions via AWS CloudFormation but used an existing service role for lambda execution, however found that no logs were being created. Here's how to fix.

IAM 

Go to the role in IAM, edit the policy and add the resource (the new lambda) 

"Resource": [
"Existing...",
"arn:aws:logs:REGION:XXXX:log-group:/aws/lambda/function-name-here:*"
]

Review and apply.

Log group created and contains logs

Immediately after updating the service role policy to add the resource, execute the function and the CloudWatch log group should be created and populated


Cheers
Quintes


Connect with me on LinkedIn or Twitter

Monday 19 March 2018

AWS Cognito User Pools, Lambda and Box integration

AWS Cognito User Pools, Lambda and Box integration


Feb 2022 - this post is permanently moved to https://architectfwd.com, my new site, and can be found here  - https://architectfwd.com/architecture/cloud/amazon-web-services-aws/cognito/user-pools/2022/01/23/aws-cognito-user-pools-lambda-and-box/ please go and bookmark that site for all of my future content.


In my previous posts I have been using Azure functions and B2C. I had a use case I wanted to try out and stood up an AWS Cognito user pool with 2 Lambda functions connecting to a box app using box sample code[1]. The process was simple and I managed to stand up the site really quickly, thus very impressed - I'd been keen on using Cognito for a while as an identity pool, and only created my AWS account the day before so all in all a great experience.

Here's what the solution would look like:


Cognito

I created a sign in / sign up policy similar to the B2C and the pool config was really easy. I created and linked up a box.com app.




I was then tasked with the box-specific lambda functions for post authentication and for creating the user in box.

Lambda 

2 Lambda and a couple of roles later and I was connected up. I used a sample angular app, wired up the AWS and box config and was A for away, except I had to increase the one of the function's timeout to 5 seconds once I stood up the angular app in Azure, it kept timing out. Cognito User Pool Lambda functions must respond within 5 seconds, not configurable.


I also needed to create roles for the Cognito and Lambda integration, specifically the first needed to be a service role, specifically a AWS lambda basic execution role. It probably needs Log policies. The second role needed a little more:



An API gateway was needed for lambda proxying to the token exchange function with box



I also needed an authorizer for the Cognito pools


CORS

CORS was a nuisance, I ended up writing headers back in all responses, just couldn't get it to work otherwise. the origin should not be a *, I know. I'll fix that, any anyway the box.com app config provides one more CORS setting which is tied to the correct domain.


Working app

It helped that I had some sample code from box. With all this configured I have a custom user pool of users who each get their own folder in a box.com instance where they can upload documents to.

I stood this up in an evening, really impressed by the AWS Cognito User Pool service and the simplicity of the interfaces. The lambda interface is awesome to use. Box.com app config is simple, and I am a long time box.com user so I think their user experience is great in general. 

Closing

I want to spend more time with AWS. I may continue with the Azure B2C as exploratory and rather throw my efforts in this direction.

References

[1] box samples on github


Cheers
Quintes


Connect with me on LinkedIn or Twitter

Wednesday 21 February 2018

Azure Functions and Azure Active Directory B2C - part 2 - postman

Azure Functions and Azure Active Directory B2C (Part 2) - postman


In my previous post I setup an Azure function and B2C for auth. I wanted to now quickly get postman to use a token from B2C. In retrospect probably would have been quicker to build the SPA, will try that next. Quickly, not so much, as I worked through the screens and dialogs in B2C to setup apps and scopes, mostly getting this error when trying to get a token from within Postman.

AADB2C90205: This application does not have sufficient permissions against this web resource to perform the operation.

In the Azure Portal, Azure B2C, Applications, go to the app created previously (mine was called functionsapp). Ensure that the APP ID URI is something, in my instance called is spaapp.

Then lower down in that blade find "API Access", by default it will contain "access the users profile". Under published scopes it auto filled "user_impersonation" for me.

Create a Postman application in B2C

In the Azure Portal, Azure B2C, Applications, create an app for Postman

Give it a name, Web app (Yes), Implicit (Yes), Reply URL (https://getpostman.com/postman), App ID URI (/api), Native Client (No)

Then lower down in that blade find "API Access", by default it will contain "access the users profile". Click Add, and choose the name of your other app (in my instance functionsapp) and choose the scopes. Save.

Under published scopes I had nothing.

Postman - Get new access token screen 

I typed these in:

Token name : anything
Grant: implicit
Call back url: https://getpostman.com/postman
Auth URL : https://login.microsoftonline.com/tenant.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_signupsignin-01
Client id: 842....
Secret:
Scope : openid https://tenant.onmicrosoft.com/spaapp/user_impersonation offline_access
Client authentication: send client credentials in body

Fail, until I got that scope and app id URI correct.

Token received!

Test the function

Test the function in the postman, and 200 OK, and the function log show my header coming through, as expected from previous post (req.headers["x-ms-client-principal-id"])

Closing

On to the front end, less time in Postman.

References

[1] https://docs.microsoft.com/en-us/aspnet/core/security/authentication/azure-ad-b2c-webapi#configure-a-sign-up-or-sign-in-policy


Cheers
Quintes


Connect with me on LinkedIn or Twitter

Wednesday 14 February 2018

Azure Functions and Azure Active Directory B2C - part 1

Azure Functions and Azure Active Directory B2C (Part 1)


Doing some work with azure functions and need authentication so I decided to try the B2C to setup an external Identity Provider.

I used [1], [2], [3] as reference.

Create a Azure AD B2C directory 

Create a new AD B2C directory, you cannot use an existing AAD directory.

Once done you want to set up policies. Do not go to Azure AD, it's not there, search in services for "Azure B2C", open that up and possibly favourite it so it is pinned on the menu.

If you did this as I did, the directory is not linked to a subscription. You need to go through MarketPlace, find B2C and choose the "Link an existing B2C to my subscription". Wait for that process and then go back to the B2C blade and view the Identity Providers and associated policies

Policies

Setup a basic sign in / sign up policy, specifying the idP, custom attributes and claims. I'm still going to integrate with another Provider, just want a basic case to work first.



Link an app

The purpose of this step is to configure an app to use the B2C directory.

A GUID will be generated.

Go back to the Sign up / sign in policy and grab the metadata endpoint URL


Go to the Function App, Function App Settings, Networking, Authentication/Authorisation and turn on the Authentication. Select "Azure Active Directory", Choose advanced and enter the GUID generated previously as well as the metadata endpoint url.

Save and wait for the notification "Save App Auth Settings"

Test the function

Test the function in the test window, you will have a 401 Unauthorized returned with error "Authentication is enabled for the function app. Disable authentication before running the function.".

Great, so grab the function URL and paste into a private browser session. You will be prompted to enter your existing email address and password, or signup. I chose the latter, and was presented with this form, which matches the fields I want captured:

I verified the account and the function was executed successfully! (Note I used the sample http trigger, which will become my secured cosmos db function)

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello sgdfg</string>

I actually added the request headers to the response like this to test:

body: JSON.stringify(req.headers)

I get 4 headers, particularly this one, which has the display name I provided in signup. Not super useful

"x-ms-client-principal-name"

But I also get "x-ms-client-principal-id":"6f8132fc-..."

I will use that in the meanwhile, but want to exchange for claims.

Closing

It was easy enough to setup the B2C and the App, then linking a function so that the function can authenticate and authorise a user. Next is to read the claims within the function to ensure I can setup cosmos db documents per user.

References

[1] https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-policies
[2] https://blogs.msdn.microsoft.com/appserviceteam/2016/06/22/app-service-auth-and-azure-ad-b2c/
[3] https://blogs.msdn.microsoft.com/hmahrt/2017/03/07/azure-active-directory-b2c-and-azure-functions/

Cheers
Quintes


Connect with me on LinkedIn or Twitter

Sunday 28 January 2018

Provisioning Office 365 Services 01 - getting started

Provisioning Office 365 Services 01


I've just completed the Provisioning Office 365 Services course through edX, mostly as a result of a number of organisations asking me over the last 3 months if I had any knowledge or experience in O365.

Thus I now do, specifically using a trial for an E3 subscription to setup a basic tenant comprising Exchange Online, SharePoint Online, Office, Teams etc. I have not setup/configured InTune (noting I do have some prior experience from an solutions architect view for mobile platforms) or Skype for Business, nor intend to, as my goal was to understand the Subscription, Tenant, Domains, Email and Administration views, and hopefully get some context on Rights Management.

Creating the tenant  


It is important to note that you must select the region/country for the subscription data location AFAIK this cannot be changed.


Also choose a domain name which is onmicrosoft.com which you also cannot change - this is the default domain name associated with the subscription.

So how do I find out my tenant name /domain name and tenant ID after the fact? Open azure portal and find the Directory ID (Guid) here and the name of the tenant is the xxxxxx.onmicrosoft.com you are most likely currently logged in as when creating the subscription. Find it under Setup -> Domains if you are unsure.

While you are on the Organisation profile you may as well select the Release Track or remember to do it later if you want some users to be on the latest releases as they come out. Most likely you actually want to do this once there are some users, so moving on..

What does my subscription look like? Like the below:



Custom Domain


You'll need to setup the custom domain for your organisation before adding users. Do this from the Setup -> Domains


I'm skipping a few screens here, in the interests of not showing my settings, but after adding the domain you need to verify you own it. Do this via the TXT OR MX record option. I chose TXT and flew through it


As example of the Verification screen:



Once verified, which is super easy, you are presented with tables of the releveant DNS Entries to add. I really think the addition of the required DNS entries on screen is helpful to get you started quickly.


Users


Add a user (regular user or Administrative)


I wanted more rights, so the Roles can be edited to give me Admin, or a mixed set of Administrative roles. These are all well documented and I won't repeat the role descriptions here.


Groups

Add some groups, there are a couple of options including O365 groups, distribution lists, mail enabled security groups and security groups.



I created one called Accounts, which would be used elsewhere, and added a user or two

Closing


This is a good start - you've created the subscription, setup a custom domain, and added users and groups. If I can work through my other thoughts before my trial ends I'll put them up here so that I can remember, and perhaps they are useful to someone else.

Cheers
Quintes



Connect with me on LinkedIn or Twitter