- log into aws console
- go to AWS health Dashboard
- ckick Scheduled changes
- click Calendar
- choose date
- click Upcomming
- choose one of events to see affected resourses
Summer
Wednesday, 4 March 2026
See affected AWS resources for upcoming events
Thursday, 15 January 2026
SFTP server
#log in
sftp leo@82.992.123.124
#after log in
# upload a file:
put test.txt
# download a file
get test.txt
# delete a file
rm test.txt
Directly copy file between the server and the local machine if can ssh to the server
# find server public ip: 100.31.47.111
# ssh to the server
ssh -i /Users/leo/path/noc.pem ec2-user@100.31.47.111
# copy file to server
scp -i /Users/leo/path/noc.pem /Users/leo/path/test.txt.gpg ec2-user@100.31.47.111:/home/ec2-user/
# copy file from server to local
scp -i /Users/leo/path/noc.pem ec2-user@100.31.47.111:/home/ec2-user/test.txt /Users/leo/path/
Decrypt gpg file
# verify have the private key
gpg --list-secret-keys
# decrypt. when prompt, provide private key phrase
gpg --decrypt --output mytest.csv mytest.csv.gpg
Monday, 12 January 2026
CORS
Error: Access to fetch at .... has been blocked by CORS
CORS stands for cross origin resource share. If use Javascript to fetch a endpoint and endpoin is not the same origin as the current page, may see the above error. Here origin is protocol + domain + port.
//host is https://examplea.com
<script>
let endpoint = "https://exampleb.com/create-order";
return fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(resp => {
if (!resp.ok) throw new Error('Network response was not ok');
return resp.json();
});
</script>
To solve the issue. For that end point of exampleb.com. the response needs to set headers such as
$response = $response->withHeader('Access-Control-Allow-Origin', "*");
return $response->withHeader('Access-Control-Allow-Headers', 'X-Requested-With,x-api-key, Content-Type, Accept, Origin, Authorization, X-Authorization-JWT, X-CSRF-Token')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
}
Wednesday, 7 January 2026
Javascript Class
Class in ECMAScript 5
function PersonType(name) {
this.name = name;
}
PersonType.prototype.sayName = function() {
console.log("your name:" + this.name);
}
let person = new PersonType("leo");
person.sayName();
Class in ECMAScript 6
class PersonType {
constructor(name) {
this.name = name;
}
sayName() {
console.log("your name:" + this.name);
}
}
let person = new PersonType("leo");
person.sayName();
Use class in web page
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="person.js"></script>
<script>
let p = new Person('leo');
p.sayName();
</script>
</head>
</html>
person.js
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log("your name:" + this.name);
}
}
// export to global namespace so index.html can see it
window.Person = Person;
Javascript Promise
Create a promise and consume a promise
example one
let p = new Promise((resolve, reject) => {
let n = Math.floor(Math.random() * 100);
let good = n % 2 == 0 ? true : false;
if (good) {
setTimeout(resolve, 100, { "dd": 1212 });
} else {
setTimeout(reject, 200, "bad2");
}
});
p.then((v) => console.log("suc", v))
.catch((v) => console.log("failed:", v));
//this is identical as the above
p.then((v) => console.log("suc", v), (v) => console.log("failed:", v));
example two
import { readFile as _readFile } from 'fs';
let p = new Promise((resolve, reject) => {
_readFile("./test.js", 'utf8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
});
p.then((data) => console.log("good", data))
.catch((err) => console.log("err", err))
Use await to consume a function which return a promise
example one
function myCreate() {
return new Promise((resolve, reject) => {
let n = Math.floor(Math.random() * 100);
let good = n % 2 == 0 ? true : false;
if (good) {
setTimeout(resolve, 100, { "dd": 1212 });
} else {
setTimeout(reject, 200, "bad2");
}
});
}
//Any exception thrown in the try block (or any rejected promise when using await) will jump to the catch.
try {
const ans = await myCreate();
console.log("ans", ans);
} catch (err) {
console.log("err:", err);
}
use async function to consume the promise
function myCreate() {
return new Promise((resolve, reject) => {
let n = Math.floor(Math.random() * 100);
let good = n % 2 == 0 ? true : false;
if (good) {
setTimeout(resolve, 100, { "dd": 1212 });
} else {
setTimeout(reject, 200, "bad2");
}
});
}
async function test() {
try {
const ans = await myCreate();
console.log("ans", ans);
} catch (err) {
console.log("err:", err);
}
}
test();
You still can use then to consume a promise returned by a function.
function myCreate() {
return new Promise((resolve, reject) => {
let n = Math.floor(Math.random() * 100);
let good = n % 2 == 0 ? true : false;
if (good) {
setTimeout(resolve, 100, { "dd": 1212 });
} else {
setTimeout(reject, 200, "bad2");
}
});
}
myCreate().then((ans) => console.log("ans", ans), (err) => console.log("err:", err));
Tuesday, 6 January 2026
Install older version vscode
Install
- go to vscode versions
- Pick a one and download
- For mac, unzip the file. Drag app file into Application folder
Prevent from upgrading automatically
- – Open VS Code.
- – Press ⌘, (Command-Comma) to open Settings.
- – In the search box type “update”.
- – Under Features → Updates find “Update: Mode” and set it to “none”.
Wednesday, 31 December 2025
AWS ECR image scan reports vulnerabilities
Question:When the image was scanned one month ago, there is no vulnerability. The same image is scanned today, and reports vulnerabilities. Why?
Answser: AWS has updated its' vulnerability definitions.
Question:Sometimes, after image is rebuilt using the same docker file, these vulnerabilities are gone. Why?
Answer: When the image is rebult, it will grab the latest libraries and these vulnerabilities may have been fixed in these new libraies. In the case, use this flag.
--no-cache
Here is an example. Scan reports vulnerabilities related to curl
Dockerfile
FROM alpine:3.19
RUN apk update && apk add curl && apk upgrade
To build
docker image build --no-cache -t leo_test:latest .
When do apk update && apk add, it will get the latest libraries. At that time, alpine may have fix the curl issue. You may check and find that curl version has been changed.
curl --version
Tuesday, 30 December 2025
X-Frame-Options header for iframe
<iframe
src="https://google.com"
width="600"
height="300"
title="Demo Iframe"
frameborder="0"
> </iframe>
Google.com will not be displayed in iframe. It is said that Google is refused to be connected. This is because that Google send out X-Frame-Options header
There are two values for this header
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
To set in apache httpd.conf
Header always append X-Frame-Options SAMEORIGIN
Header always append X-Frame-Options DENY
For the first option, will display content of the same domain. For the second option, will not display content from any domain
Thursday, 4 December 2025
ECS service and target group
- associate ECS service to load balancer
- define target group for load balancer
- running tasks of this ECS service become targets of this target group
#cloudformation template snippet
Service:
Type: "AWS::ECS::Service"
Properties:
Cluster: !FindInMap [BuildEnvironment, !Ref 'EnvironmentType', "cluster"]
DesiredCount: !FindInMap [BuildEnvironment, !Ref 'EnvironmentType', "desire"]
LoadBalancers:
- ContainerName: !Sub "${EnvironmentType}-${APP}"
ContainerPort: 80
TargetGroupArn: my_target_group_arn
Monday, 1 December 2025
Encrypt and decrypt password using PHP sodium
Encrypt password
<?php
/**
* encrypt.php
*/
$masterKey = "canyouguess";
$passwordToEncrypt = "top-secret";
//ecncypt password
$code = encrypt($masterKey, $passwordToEncrypt);
echo "code: ", $code, "\n";
/**
* @param $masterKey
* @param $password
* @return string
* @throws SodiumException
*/
function encrypt($masterKey, $password)
{
// Derive a subkey of the correct length for secretbox
$key = sodium_crypto_generichash($masterKey, '', SODIUM_CRYPTO_SECRETBOX_KEYBYTES
);
// Generate a random nonce
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
// Encrypt
$ciphertext = sodium_crypto_secretbox($password, $nonce, $key);
// Prepend nonce for later decryption, and base64-encode the lot
return base64_encode($nonce . $ciphertext);
}
In the directory of encrypt.php, run:
docker run -it --rm -v "$PWD":/usr/src -w /usr/src php:8.2-cli php encrypt.php
Output:
code: qKUilnBOnSPIOmKnwIoJAdOaC+9lhud/0eiTekLPokmuImFiRpuHvKG6AoUs7eT7fBY=
Decrypt code to get password
If do not have master key, there is no way to decrypt the code
<?php
/**
* decrypt.php
*/
$masterKey = "canyouguess";
$code = "qKUilnBOnSPIOmKnwIoJAdOaC+9lhud/0eiTekLPokmuImFiRpuHvKG6AoUs7eT7fBY=";
//decrypt password using master key
$password = decrypt($masterKey, $code);
echo "password: ", $password, "\n";
/**
* @param $masterKey
* @param $code
* @return string
* @throws SodiumException
*/
function decrypt($masterKey, $code)
{
$raw = base64_decode($code, true);
if ($raw === false) {
throw new RuntimeException('Invalid base64');
}
// same derived subkey
$key = sodium_crypto_generichash($masterKey, '', SODIUM_CRYPTO_SECRETBOX_KEYBYTES
);
$nonceLen = SODIUM_CRYPTO_SECRETBOX_NONCEBYTES;
if (strlen($raw) < $nonceLen) {
throw new RuntimeException('Ciphertext too short');
}
// extract nonce and ciphertext
$nonce = mb_substr($raw, 0, $nonceLen, '8bit');
$ciphertext = mb_substr($raw, $nonceLen, null, '8bit');
// decrypt & verify
$plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
if ($plaintext === false) {
throw new RuntimeException('Decryption failed or message forged');
}
return $plaintext;
}
In the same directory of decrypt.php, run:
docker run -it --rm -v "$PWD":/usr/src -w /usr/src php:8.2-cli php decrypt.php
Output:
password: top-secret
Monday, 17 November 2025
Import and export in AWS CloudFormation
- ContainerName: !Sub "${AWS::StackName}"
ContainerPort: 80
TargetGroupArn: { "Fn::ImportValue" : { "Fn::Join" : [ "-", [ { "Ref" : "EnvironmentType" }, "leo-elb-elb-target-group"]] }}
If EnvironmentType is sandbox, we are importing sandbox-leo-elb-elb-target-group as TargetGroupArn
# part of codes from stack sandbox-leo-elb
# export a resource called leo-elb-elb-target-group
# click Outputs tab in AWS console for this stack. Also see Export Name: leo-elb-elb-target-group
Outputs:
ELBTargetGroupHTTP:
Description: The target group
Value: !Ref ELBTargetGroup
Export:
Name: !Sub "${AWS::StackName}-elb-target-group"
Wednesday, 12 November 2025
Git cherry pick
how to cherry pick codes from development to staging
- need to find commit hash using git log
- git checkout release/1-staging
- git checkout -b feature/SMP-7777
- git cherry-pick hash
- git push --set-upstream origin feature/SMP-7777
- create code review
If pick mutiple commits, start cherry pick from old one.
//example
git checkout master
git checkout -b feature/my-4247-hot-fix
git cherry-pick cd5861fb4c098855fe99b1eb74790874c6be4570 22dfcc0dd6064029da786637e3ceb3b5b5d00719
git push -u origin feature/my-4247-hot-fix
Monday, 18 August 2025
If deploy process stuck because of AWS stack update
- cancel Jenkin release process
- go to AWS cloudformation. go to Stack Action. click Cancel update stack from drop down.
- wait for update_rollback_complete state
Friday, 8 August 2025
AWS Lambda
To access AWS Cloudwatch Logs for Lambda function
- Click Monitor tab
- Click view CloudWatch Logs link
Use environment variable in node.js
//here SHARED_MS_BUCKET is env variable name
Bucket: process.env.SHARED_MS_BUCKET
Sunday, 11 May 2025
Edit host file for Window 11 WSL (Windows Subsystem for Linux)
You need to edit the following file using notepad and run as admin
C:\Windows\System32\drivers\etc\hosts
If you edit subsystem linux's /etc/hosts, it will not affect browser such as Google Chrome
Access two github accounts in one linux machine
Assume you already can access your person github repositories using public key id_rsa.pub
- Create another ssh private / public key pair
# file name: ~/.ssh/id_rsa2 ssh-keygen - upload public key to your company's github
- create a ssh config at .ssh/config
Host github.com HostName github.com User git IdentityFile ~/.ssh/id_rsa AddKeysToAgent yes ServerAliveInterval 60 ServerAliveCountMax 30 # Work GitHub account Host github-work HostName github.com User git IdentityFile ~/.ssh/id_rsa2 AddKeysToAgent yes ServerAliveInterval 60 ServerAliveCountMax 30 - clone work repository
git clone git@github-work:mycompany/jackt.git - clone your person repository as normal because it will use the default ssh config
Tuesday, 15 April 2025
Access Mysql Database hosted on AWS EC2
To access the database, need to set up two things.
Step 1: add rule to the security group attached to the instance
- Edit inbound rule of the security group
- add a rule. Type: MYSQL/Aurora Soure: custom such as 137.229.127.0/24
Step 2: update privilidge of Mysql database
- log into the database as root or admin
#works for mysql 5.7.8 and up. To change a user's ip RENAME USER 'teau'@'51.27.292.63' TO 'teau'@'125.256.111.%'; # for new user, need to grant permission- FLUSH PRIVILEGES;
Trouble shooting
If do not do the step one, most likely will see a connection timeout
If do not do the second step, will see something like
[MySQL][ODBC 8.0(w) Driver]Host '*.*.***.**' is not allowed to connect to this MySQL server
Unable to connect to the MySQL server "***.***.**.**". Check that the server is running and that you have
access privileges to the requested database.
Some useful Mysql commands
select version();
select user, host from mysql.user;
SHOW GRANTS FOR 'leo'@'52.30.111.16';
Tuesday, 25 March 2025
Schedule post to an end point using Amazon EventBridge Rules
- set up a SNS topic
- Create a subscription for this SNS topic. Choose protocol https and enter end point such as
https://paysomething.sandbox.mysite.io/v1/tasks/process - Go to Amazon EventBridge to create a rule
- Make the above SNS topic as target of the rule, and type is Schedule
Friday, 14 March 2025
AWS WAF
Bock ips to elb
- Click IP set tab
- Click Create IP set button
- Given name, description and IP addresses
- Click Create IP set button to save the IP set
- Click Web ACLs tab
- Click Create Web ACL button
- Follow steps to create web ACL. Add the above ip set rule and action is block
- For Default web ACL action for requests that don't match any rules, choose allow
-
- Click Web ACLs tab agin. The newly created ACL should show up in the list
- Click that ACL
- Click Associate AWS resources tab
- Click Add AWS resource button
- Select the ebl and assoicate it to this Web ACL
- Test it using your own ip
- Go back to that Web ACL home page to check traffic log
Tuesday, 4 March 2025
Add Custom Http Header
Using curl
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'cookiename: blue',
'X-Apple-Store-Front: 143444,12'
]);
Google Chrome
Use ModHeader extension
Postman
Click Headers tab to add custom header