AWS SSM Parameter Store IAM Policy for restricting by Path and Tag

I wanted to restrict access to some parameters based on the path and tag.

Say, I have a key:
/production/Param1=Value1
with a tag:
Application1=One

I was expecting a policy like this:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ssm:GetParameterHistory",
"ssm:ListTagsForResource",
"ssm:GetParametersByPath",
"ssm:GetParameters",
"ssm:GetParameter"
],
"Resource": "arn:aws:ssm:::parameter/production/*", "Condition": { "StringEquals": { "ssm:resourceTag/Application1": "One" } } }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "tag:GetResources", "ssm:DescribeParameters" ], "Resource": ""
}
]
}

I had to do

# aws ssm describe-parameters --parameter-filters "Key=tag:Application1,Values=One" --output json | \ #filter by the tag
jq ".Parameters[].Name" | \ # get parameter name
xargs -I {} aws ssm get-parameter --name {} --with-decryption # get the parameter

{
"Parameter": {
"Name": "/production/Param1",
"Type": "String",
"Value": "Value1",
"Version": 1,
"LastModifiedDate": "2020-08-09T18:29:51.197000+10:00",
"ARN": "arn:aws:ssm:ap-southeast-2:378624334311:parameter/production/Param1",
"DataType": "text"
}
}

If you know the parameter name, get-parameters is simpler:

aws ssm get-parameters --name "/production/Param1" --profile k7-test
{
"Parameters": [
{
"Name": "/production/Param1",
"Type": "String",
"Value": "Value1",
"Version": 1,
"LastModifiedDate": "2020-08-09T18:29:51.197000+10:00",
"ARN": "arn:aws:ssm:ap-southeast-2:******:parameter/production/Param1",
"DataType": "text"
}
],
"InvalidParameters": []
}

It would have been simpler to filter by tags when using get-parameters-by-path, but a known issue with AWS:
https://github.com/aws/aws-cli/issues/2850
prevents us from doing that.

AWS Codecommit – PR and Comits with large files

AWS Codecommit console UI fails to display a diff when viewing PRs or Commits with large files (in my case a 7125 line XML file was part of the PR that failed to render the diff).

AWS support confirmed that this is a limitation as of now and failed to provide further details (on what the limit is or when this would be fixed).

It makes reviewing a little bit longer as one has to do the review out of the Console and then Approval/Disapproval happens within the console. It is a pain, to be honest.

Beware 🙂

MySQL substring start is one based

To my surprise, MySQL SUBSTRING functions start position is one based. A start position of ‘0’ will return an empty string.

If you would like to get the first 100 characters of a column named ‘my_column’ you will need to use SUBSTRING(‘my_column’, 1, 100). Using SUBSTRING(‘my_column’, 0, 100). will return an empty string.

Postgres and Microsoft SQL server also seem to be one based, but, have different behaviour when a ‘0’ is passed for the start position.



Using Generators to flatten a JSON doc in PHP

To flatten a JSON like this:

{
   "addresses" : [
     {
       "line1" : "123 Livingstone Rd",
       "id" : 23444555,
       "addressSummaryType": "Building",
       "subAddresses": {
         "Level1": [
           {
             "line1" : "Level 2",
             "id" : 266887373,
             "Level2": [
               {
                 "line1": "Suite 201",
                 "id" : 276888890
               }
             ]
           }
         ]
       }
     },
     {
       "addressSummaryType": "Building",
       "line1" : "124 Livingstone Rd",
       "id" : 2562672
     }
   ]
 }

to:

array(2) {
  ["id"]=>
  int(23444555)
  ["address"]=>
  string(18) "123 Livingstone Rd"
}
array(2) {
  ["id"]=>
  int(266887373)
  ["address"]=>
  string(26) "Level 2 123 Livingstone Rd"
}
array(2) {
  ["id"]=>
  int(276888890)
  ["address"]=>
  string(36) "Suite 201 Level 2 123 Livingstone Rd"
}
array(2) {
  ["id"]=>
  int(2562672)
  ["address"]=>
  string(18) "124 Livingstone Rd"
}

I used the following code:

foreach(flattenAddress($addressObj->addresses) as $flattenedAddress) {
      var_dump($flattenedAddress);
 }

 function flattenAddress($addresses, $baseAddress = '', $level = 0)
 {
     foreach ($addresses as $address) {
         $nextLevel = "Level" . ($level + 1);
         if (property_exists($address, "addressSummaryType")) { //root
             $baseAddress = $address->line1;
             yield ["id" => $address->id, "address" => $baseAddress];
             if (property_exists($address, "subAddresses")) {
                 yield from flattenAddress($address->subAddresses->{$nextLevel}, $baseAddress, ($level + 1));
                 continue; // recurse don't reset level
             }
         } else { //subaddresses
             $subAddress =  $address->line1 . " " . $baseAddress;
             yield ["id" => $address->id, "address" => $subAddress];
             if (property_exists($address, $nextLevel)) {
                 yield from flattenAddress($address->{$nextLevel}, $subAddress, ($level + 1));
                 continue; // recurse don't reset level
             }
         }
         $level = 0; //reset for next root
     }
 }


Add extra validation rules to Laravel ForgotPassword

I wanted to add a captcha to the Forgot Password form, so I ended up doing this to the default ForgotPasswordController:

use Validator;
use \Illuminate\Http\Request;
 
class ForgotPasswordController extends Controller {
 
protected function validateEmail(Request $request)
{
    Validator::make(
        $request->all(),
        [
            'email' => 'required|email',
            'captcha' => 'required|captcha', // extra param to be validated
        ]
   )->validate();
}

Only relevant bits are shown there.

ES6 support on iOS9

Recently while building a Cordova based app, few users complained that they were seeing blank pages or cryptic error messages. Someone mentioned they were on iOS9. Over the weekend, as I ran the app on a simulator, I noticed an error in Safari. And, that’s when I realized ES6 features and syntax is not fully supported in iOS9.  Please see here: ES6 Compatibility (check unstable platforms)

So be-aware of ES6 features compatibility (unless you can transpile/polyfill every bit of code)

Jenkins parallel pipeline

I was very excited to know about the ‘parallel’ feature in Jenkins Pipeline, but, there are many gotchas while making  use of the pipeline feature (many of which are documented here: Jenkins Pipeline Example). After trying and reading a few different solutions, following worked for me (notice in screenshot that the browser jobs run in parallel !)

pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        echo 'hello'
      }
    }
    stage('Test') {
      steps {
        script {
            def jobs = [:]
            def browsers = ["Chrome", "Firefox"]
            for (int i = 0; i < browsers.size(); i++) {
                def browser = browsers.get(i)
                def jobName = "printing $browser"
                jobs[jobName] = doJob(browser)
            }
            parallel jobs
        }
      }
    }
    stage('Deploy') {
      steps {
        echo 'deploying'
      }
    }
  }
}

def doJob(browser) {
    return {
        node {
            echo "testing in $browser"
        }
    }
}

React Native: Application is not registered

- This is either due to a require() error during initialisation or failure to call AppRegistry.registerComponent.

I had been struggling with this for some time and the answer was right there… I had to make sure I called AppRegistry.registerComponent with the right params/appname – I had renamed my app and forgot to update the class name and also the name passed to registerComponent.

And, one way to rename a project is by renaming in package.json and then running react-native upgrade.

High System CPU usage

After upgrading a webserver running Apache to Debian Jessie (from Wheezy), I noticed that the system CPU usage was higher.  Running an strace on one of the Apache processes was giving me very little info:


strace -c -p 10112
Process 10112 attached - interrupt to quit
^CProcess 10112 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
95.71 28.549784 3172198 9 4 futex

I had previously tried to spread interrupts across cores and also limited network activity – as they are something one can do to work out why System CPU is high – but they didn’t bring down the CPU usage.

One culprit remained: Futex/Mutex locks. I changed the default Mutex [1] to file and magically the System CPU usage went down.

[1] Apache 2.4 Mutex doc