<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[NY]]></title><description><![CDATA[NY]]></description><link>https://nayyaung.com/</link><image><url>http://nayyaung.com/favicon.png</url><title>NY</title><link>https://nayyaung.com/</link></image><generator>Ghost 4.47</generator><lastBuildDate>Fri, 20 Mar 2026 01:17:03 GMT</lastBuildDate><atom:link href="https://nayyaung.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[What does CORS prevent?]]></title><description><![CDATA[What does CORS do? Why use CORS to limit specific domains to call your API? Maybe it prevents a few bad things...]]></description><link>https://nayyaung.com/what-is-cors/</link><guid isPermaLink="false">628bd667983ccf00016718c9</guid><category><![CDATA[Programming]]></category><category><![CDATA[Security]]></category><category><![CDATA[Coding]]></category><dc:creator><![CDATA[Nay Yaung]]></dc:creator><pubDate>Mon, 23 May 2022 18:00:30 GMT</pubDate><content:encoded><![CDATA[<p>CORS = <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">Cross-Origin Resource Sharing</a></p><p>Some of the software engineers I have met (not a lot, I hope) casually add CORS in the API because it wasn&apos;t working when their frontend tries to call it. They google around the error and just add CORS with wildcard value &apos;*&apos;, allowing all domains to now able to access the API from the browser. </p><p>Once it works, CORS settings is left forgotten and people move on.</p><p>Here, we take a moment to appreciates CORS a little bit more.</p><p>Allowing all domain to be able to call your API is dangerous. What CORS does is allow you to configure only the websites with specific domains can call your API. By doing so, it prevents a few things:</p><p>First, it prevents the API from being able to access by any random website. </p><p>Imagine the scenaio where wildcard &apos;*&apos; is used for CORS setting. Alice has an API which is only meant for Alice&apos;s website, Bob creates another website that consumes Alice&apos;s API which has some expensive operations. Now, Bob can abuse Alice&apos;s API, the browsers from Bob&apos;s users will then be executing API calls to Alice&apos;s API server, taking up resources - one variant of DDoS attack. </p><p>Second, it prevents something more subtle - malicious hackers trying to steal users&apos; credential information. Here is how it works.</p><p>Imagine; Alice&apos;s API sets some cookies on the browser, Bob&apos;s Web UI now executes GET call to Alice&apos;s API by setting &apos;withCredentials&apos; value to true.</p><pre><code>var xhr = new XMLHttpRequest();
xhr.open(&apos;GET&apos;, &apos;http://alice-api.com/&apos;, true);
xhr.withCredentials = true;
xhr.send(null);
</code></pre><p>Now this request will sent back the cookies previously set by alice-api on the user&apos;s browser. The cookies can contain user&apos;s credential information used to authenticate to alice-api. </p><p>On the server side, there is something called <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials">Access-Control-Allow-Credentials</a> header, &#xA0;of which the value can be either true or the header is ommited. &#xA0;It goes hand-in-hand with CORS <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin">Access-Control-Allow-Origin</a> header.</p><p>Almost all the CORS library support setting <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials">Access-Control-Allow-Credentials</a> header value which is either true or false (which means the header is not included in the response at all). If the header value is set to true, it allows JavaScript of whatever web application making API call can see the response. Otherwise, the app (JavaScript) can&apos;t see the response value. This is important because anything that requires user&apos;s credential is considered important and equally sensitive as user&apos;s credentials. </p><h3 id="scenario-1-intended-website-to-api">Scenario 1: Intended Website to API</h3><p>This is the example response when Access-Control-Allow-Credentials value is set to true, and Access-Control-Allow-Origin value is set to intended website domain.</p><figure class="kg-card kg-image-card"><img src="http://nayyaung.com/content/images/2022/05/image-2.png" class="kg-image" alt loading="lazy" width="395" height="587"></figure><p>In this case, Origin is properly set to the website&apos;s domain. Everything works fine. Cookies are carried over and sent back to the API, which in turn also sends back the response, which JavaScript can access.</p><p>Now another example where Access-Control-Allow-Credentials is not included and Access-Control-Allow-Origin value is set to the intended website domain.</p><figure class="kg-card kg-image-card"><img src="http://nayyaung.com/content/images/2022/05/image-3.png" class="kg-image" alt loading="lazy" width="514" height="169"></figure><p>Now JavaScript cannot see the response and fails with the reason &quot;CORS missing allow credentials&quot; although the cookies are being sent to the API server, too.</p><h3></h3><h3 id="scenario-2-malicious-website-to-api">Scenario 2: Malicious Website to API</h3><p>This is the example response when Access-Control-Allow-Credentials value is set to true, and Access-Control-Allow-Origin value is set to intended domain.</p><!--kg-card-begin: html--><img src="http://nayyaung.com/content/images/2022/05/image.png"><!--kg-card-end: html--><p>It fails with &quot;CORS Allow Origin Not Matching Origin&quot; error. </p><p>Take note that cookies which belong to Alice&apos;s Website, set by Alice&apos;s API, are still being sent over in the request as shown in the screenshot below.</p><figure class="kg-card kg-image-card"><img src="http://nayyaung.com/content/images/2022/05/image-6.png" class="kg-image" alt loading="lazy" width="517" height="595"></figure><p>There you have it. Bob&apos;s website simply tries to execute GET API from Alice API. It sends legitimate cookies from Alice&apos;s website set by Alice&apos;s API back to the API and tries to get hold of the sensitive information from the response.<br>But, thanks to CORS, &#xA0;&quot;Allow Origin Not Matching Origin&quot; error prevents user from Bob&apos;s malicious website faking and stealing sensitive information, or even doing some destructive action. </p><p>Another thing that makes CORS more secure is we can&apos;t set Access-Control-Allow-Origin to &apos;*&apos; wildcard when Access-Control-Allow-Credentials value is set to true (quote below), so that malicious websites can&apos;t steal user&apos;s protected data just because some engineer accidentally sets &apos;*&apos; as &#xA0;Access-Control-Allow-Origin value.</p><!--kg-card-begin: markdown--><blockquote>
<p>Note: When responding to a credentialed requests request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the &quot;*&quot; wildcard.</p>
</blockquote>
<p>Ref:  <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS</a></p>
<!--kg-card-end: markdown--><p></p><p>I hope this helps understand CORS a little bit more.</p><p>PS: CORS is only for browser. It doesn&apos;t do anything if you are using curl command or any other manual tools.</p>]]></content:encoded></item><item><title><![CDATA[Setting up Ingress on EKS with TLS Certificate from ACM]]></title><description><![CDATA[How to terminate SSL at Elastic Load Balancer hosted in EKS using Ingress]]></description><link>https://nayyaung.com/setting-up-ingress-on-eks-with-tls-certificate-from-acm/</link><guid isPermaLink="false">628bd667983ccf00016718c8</guid><category><![CDATA[aws]]></category><category><![CDATA[kubernetes]]></category><category><![CDATA[eks]]></category><category><![CDATA[deployment]]></category><dc:creator><![CDATA[Nay Yaung]]></dc:creator><pubDate>Tue, 04 Jan 2022 09:30:27 GMT</pubDate><content:encoded><![CDATA[<p>The scenario is when you want to terminate SSL at Elastic Load Balancer hosted in EKS.</p><p>There is <a href="https://aws.amazon.com/premiumsupport/knowledge-center/terminate-https-traffic-eks-acm/">an article from AWS</a> explaining how to achieve this using <a href="https://kubernetes.io/docs/concepts/services-networking/service/">Kubernetes Service</a>. But Services on EKS create Classic Load Balancer instead of Application Load Balancer which is created if you use <a href="https://kubernetes.io/docs/concepts/services-networking/ingress/">Ingress</a>.</p><p>Note: <a href="https://aws.amazon.com/elasticloadbalancing/features/">Application Load Balancer is more flexible than Classic one</a> but this is not the subject of this article.</p><p>For those who just want to see the code, GitHub repository is <a href="https://github.com/nayyaung/EKS_Ingress_SSL_Termination">here</a>.</p><h3 id="prerequisites">Prerequisites</h3><p>To do this, please make sure you have all other things setup such as having a domain set up on Route53 and a certificate requested from ACM. And make sure you have already had AWS Load Balancer controller set up in your EKS cluster.</p><p>You can check if you have already set up AWS Load Balancer by running the command:</p><!--kg-card-begin: markdown--><pre><code class="language-shell">kubectl get deployment -n kube-system aws-load-balancer-controller
</code></pre>
<!--kg-card-end: markdown--><p>If you don&apos;t it set up, then follow <a href="https://docs.aws.amazon.com/eks/latest/userguide/aws-load-balancer-controller.html">this guide</a> to create AWS Load Balancer Controller.</p><h3 id="process">Process</h3><p>Once all the prerequisites are in place, create a file called deployment.yaml with the content below:</p><!--kg-card-begin: markdown--><pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo-pod
  template:
    metadata:
      labels:
        app: echo-pod
    spec:
      containers:
      - name: echoheaders
        image: k8s.gcr.io/echoserver:1.10
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
</code></pre>
<!--kg-card-end: markdown--><p>Then, run</p><!--kg-card-begin: markdown--><pre><code class="language-bash">kubectl apply -f deployment.yaml
</code></pre>
<!--kg-card-end: markdown--><p>Now, the pods should be up and running</p><!--kg-card-begin: markdown--><pre><code class="language-bash">kubectl get pods -l app=echo-pod
</code></pre>
<!--kg-card-end: markdown--><p>Next, create a service with a file called service.yaml. Note that we are using NodePort instead of LoadBalancer type.</p><!--kg-card-begin: markdown--><pre><code class="language-yaml">apiVersion: v1
kind: Service
metadata:
  labels:
    app: echo-pod
    app.kubernetes.io/name: echo-pod
  name: echo-pod
spec:
  ports:
  - name: http
    nodePort: 30162
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: echo-pod
  type: NodePort
</code></pre>
<!--kg-card-end: markdown--><p>NodePort is being used here but ClusterIP can also be used. </p><p>Now, the service should be created.</p><!--kg-card-begin: markdown--><pre><code class="language-bash">kubectl get service -l app=echo-pod
</code></pre>
<!--kg-card-end: markdown--><p>Next, create ingress file. Take note the certificate-arn annotation, where you have to use your certificate ARN from ACM. Host name must be updated to your host name, too.</p><!--kg-card-begin: markdown--><pre><code class="language-yaml">apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:xxxxx:certificate/xxxxxxx
    alb.ingress.kubernetes.io/listen-ports: &apos;[{&quot;HTTP&quot;: 80}, {&quot;HTTPS&quot;: 443}]&apos;
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/actions.ssl-redirect: &apos;{&quot;Type&quot;: &quot;redirect&quot;, &quot;RedirectConfig&quot;: { &quot;Protocol&quot;: &quot;HTTPS&quot;, &quot;Port&quot;: &quot;443&quot;, &quot;StatusCode&quot;: &quot;HTTP_301&quot;}}&apos;
  labels:
    app: echo-pod
    app.kubernetes.io/name: echo-pod
  name: echo-pod-ingress
spec:
  ingressClassName: my-alb-ing-class # or whatever ingress class name of ELB
  rules:
  - host: nayyaung.com # change it to your host name here
    http:
      paths:
      - path: /*
        pathType: ImplementationSpecific
        backend:
          service:
            name: ssl-redirect
            port:
              name: use-annotation
      - path: /*
        pathType: ImplementationSpecific
        backend:
          service:
            name: echo-pod
            port:
              name: http        
  tls:
  - hosts:
    - nayyaung.com # change it to your host name here
</code></pre>
<!--kg-card-end: markdown--><p>Finally, you will see ALB being created. Wait for it to reach Active stage then go over to Route53 console to create host record using your host name and map it to the ALB just being created.</p><h3 id="one-interesting-things-to-notice">One interesting things to notice: </h3><p>&quot;listen-ports&quot; annotation has both p0rt 80 and 443. And the actions.ssl-redirect annotation is set up to redirect http traffic to https using ssl-redirect action. ssl-redirect action must be the first rule so that ALB will evaluate it first, details in <a href="https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/tasks/ssl_redirect/">here</a>. </p><p>So, if the user uses port 80, ALB will reroute it to port 443, with given SSL certificate on that port, and terminate it before routing it via the ingress rule to echo-pod which is using only port 80 (without SSL).</p><p>Again, the code is available on <a href="https://github.com/nayyaung/EKS_Ingress_SSL_Termination">my GitHub repository</a>.</p><p>Thanks for reading.</p>]]></content:encoded></item><item><title><![CDATA[Difference Between XSS and CSRF]]></title><description><![CDATA[<p></p><p>XSS = Cross-Site Scripting , &#xA0;CSRF = Cross-Site Request Forgery </p><!--kg-card-begin: markdown--><h3>XSS</h3>
<p>It is a script injected inside the web application of the (innocent) host by</p>
<ul>
<li>Inserting script into the inputs of the website such as comment box, which will then be executed when users use the website.</li>
<li>Placing it in the URL</li></ul>]]></description><link>https://nayyaung.com/xss-vs-csrf/</link><guid isPermaLink="false">628bd667983ccf00016718c7</guid><category><![CDATA[Coding]]></category><category><![CDATA[Programming]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Nay Yaung]]></dc:creator><pubDate>Sun, 26 Sep 2021 11:39:10 GMT</pubDate><content:encoded><![CDATA[<p></p><p>XSS = Cross-Site Scripting , &#xA0;CSRF = Cross-Site Request Forgery </p><!--kg-card-begin: markdown--><h3>XSS</h3>
<p>It is a script injected inside the web application of the (innocent) host by</p>
<ul>
<li>Inserting script into the inputs of the website such as comment box, which will then be executed when users use the website.</li>
<li>Placing it in the URL of the query string of actual host and letting the user click the link.</li>
</ul>
<p>XSS is executed inside the host domain so that it is more affective and can bypass a lot of browser&apos;s prevention. It can read all the information from the local storage or cookies written by the targeted host and can send this information over to malicious website for further actions.</p>
<p>The protection is to sanitize all the user inputs and to encode and escape all the character so that the injected code doesn&apos;t execute when it gets rendered on the browser. Full explanation can be found on the <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#Output_Encoding_Rules_Summary">OWASP website</a>.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h3 id="csrf">CSRF</h3>
<p>As the name implies, this is meant to trick user into doing some unintended action. This is done by simulating legitimate action performed by the URL but with a different parameters and send it to unaware users pretending to be an innocent link.</p>
<p><code><a href="https://www.some-legitimate-bank.com?action=transfer_money_to_hacker_account&amp;value=1000">https://www.some-legitimate-bank.com?action=transfer_money_to_hacker_account&amp;value=1000</a></code></p>
<p>If the user clicks the link crafted and given by malicious hacker while his browser session on the targeted website is still alive, it will end up performing the action intended by the malicious hacker.</p>
<p>CSRF can be prevented by one-time challenge called CSRF token and most of the reputable modern web frameworks has it built-in. Full explanation on how to protect it is explained also on <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html">OWASP website</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Graphic Card (GPU) Intermittently Undetected on Boot]]></title><description><![CDATA[<p></p><p>It happened to me few months ago. When the PC boots, graphic doesn&apos;t get detected and only built-in graphic port from the motherboard works.</p><p>Several method such as re-seating, cleaning dust from the PCI slot and the card have been tried in vain. The only solution that works</p>]]></description><link>https://nayyaung.com/graphic-card-intermittently-undetected-on-boot/</link><guid isPermaLink="false">628bd667983ccf00016718c6</guid><category><![CDATA[hardware]]></category><category><![CDATA[tips]]></category><category><![CDATA[amazon]]></category><dc:creator><![CDATA[Nay Yaung]]></dc:creator><pubDate>Wed, 22 Sep 2021 05:19:22 GMT</pubDate><content:encoded><![CDATA[<p></p><p>It happened to me few months ago. When the PC boots, graphic doesn&apos;t get detected and only built-in graphic port from the motherboard works.</p><p>Several method such as re-seating, cleaning dust from the PCI slot and the card have been tried in vain. The only solution that works is to clean both the PCI slot and the card&apos;s contacts with copious amount of Contact Cleaner made by any good brand (like this one from amazon <a href="https://amzn.to/3nUMS1K">https://amzn.to/3nUMS1K</a> ) and let it dry before putting the card back in.</p><p>Good Luck!</p><!--kg-card-begin: markdown--><p><sub>Disclaimer: Amazon referral code included</sub></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[OpenStdin (Console.Read, etc...) with AWS ECS]]></title><description><![CDATA["interactive" parameter in the ECS task definition]]></description><link>https://nayyaung.com/using-stdin-with-ecs/</link><guid isPermaLink="false">628bd667983ccf00016718c5</guid><category><![CDATA[Programming]]></category><category><![CDATA[Coding]]></category><category><![CDATA[aws]]></category><category><![CDATA[short-read]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[Nay Yaung]]></dc:creator><pubDate>Fri, 09 Jul 2021 04:14:51 GMT</pubDate><content:encoded><![CDATA[<p></p><p>If you use AWS ECS to deploy a container that uses openStdin, such as Console.Read() in C#, to keep the application alive, make sure &quot;<a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_interactive">interactive</a>&quot; parameter in the ECS task definition is set to &quot;true&quot;.</p><p> <br>Otherwise, your container in ECS will keep on exiting itself consistently with Exit Code 0 (zero).<br>It behaves differently if you run it on docker engine, i.e. not specifying &quot;interactive&quot; flag will still keep the container running. But ECS will take it down if &quot;interactive&quot; is not set to true when you are using stdin as a mean to keep the application alive.<br><br>The other option is to let the main thread sleep infinitely if you don&apos;t want to use stdin.</p>]]></content:encoded></item><item><title><![CDATA[Code Simplicity & Perfection]]></title><description><![CDATA[Reasonably simple code is perfect code.]]></description><link>https://nayyaung.com/simplicity-perfection/</link><guid isPermaLink="false">628bd667983ccf00016718c4</guid><category><![CDATA[Programming]]></category><category><![CDATA[Coding]]></category><dc:creator><![CDATA[Nay Yaung]]></dc:creator><pubDate>Tue, 06 Jul 2021 08:17:20 GMT</pubDate><content:encoded><![CDATA[<p></p><p>If you are a software engineer and you have passed the stage of writing advanced <a href="https://en.wikipedia.org/wiki/Spaghetti_code">Spaghetti code</a> using <a href="https://en.wikipedia.org/wiki/Big_ball_of_mud">big ball of mud</a> design pattern, you reach a stage where you want to write the perfect code with proper design structure, using all fancy design patterns and abstraction.</p><p>But does it stop there? For some people and some organization, yes. Not sure it is for the best. Using advanced patterns with heavy abstraction everywhere usually comes with a cost, especially when it is not necessary. </p><p>At the end of the day, it is not only about how beautiful your code is. It is also about being easy to read and maintainable by someone else. Complex code takes longer to modify by someone else who is not the original developer. It adds the higher chance of your successor rewriting your code (breaking DRY) for the sake of simplicity for him/her. There is a balance to strike. If you don&apos;t know the balance, be err in favour of simplicity. More often than not, being (reasonably) simple is better than being perfect.</p><p></p><p><u>Fancy Vocabulary</u></p><p><strong>Brilliant Jerk : </strong>a software engineer who is relatively knowledgeable and smart but refuses to see more than technical aspects.</p><p>This is someone who has strong technical skills but not willing to acknowledge that there is human aspects in the project. That person will fight with everyone to get the most aesthetically pleasing (to him/her) code. </p><p>Organizations may or may not want that kind of people as an employee but, as a rule of thumb, don&apos;t be that person. Better to stay as a team player, unless you are Maverick from the movie Top Gun.</p>]]></content:encoded></item><item><title><![CDATA[About This Website]]></title><description><![CDATA[Personal Website of Nay Yaung...]]></description><link>https://nayyaung.com/about-3/</link><guid isPermaLink="false">628bd667983ccf00016718c3</guid><category><![CDATA[About]]></category><dc:creator><![CDATA[Nay Yaung]]></dc:creator><pubDate>Tue, 06 Jul 2021 06:48:57 GMT</pubDate><content:encoded><![CDATA[<p></p><p>This is the personal website of Nay Yaung.<br>He is a software engineer originally from Myanmar and this website here expresses his own personal views.</p><p>Go to <a href="http://nayyaung.com/contact/">contact page</a> for more information.</p>]]></content:encoded></item></channel></rss>