AKS/Kubernetes/HELM Cheat Sheet

Switch Azure subscription
az account set --subscription {subscription_id}
Switch AKS credentials
az account set --subscription {subscription_id}
Display current context
kubectl config current-context
List all contexts
kubectl config get-contexts
Switch current context
kubectl config use-context {context_name}
Delete context
kubectl config delete-context {context_name}
Rename context
kubectl config rename-context {old_context_name} {new_context_name}
Display logs from a container
kubectl logs -l {deployment_label}
Display logs from an init container (db migration)
kubectl logs -l {deployment_label} -c {init_container_name}
Display all deployments
helm ls -a
Display information related to deployment
helm get all {deployment_name}
Display deployment status
helm status {deployment_name}
Restart deployment
kubectl rollout restart deployment {deployment_name}
List all pods in namespace
kubectl get pods -n {namespace_name}
Display values for helm deployments
helm get values {deployment_name}
Delete workload from k8 cluster
kubectl delete deployment.apps {workload_name}
Delete service from k8 cluster
kubectl delete service {service_name}
Create deployment using YAML file
kubectl create -f {file_name}

Delete deployment using YAML file

kubectl delete -f {file_name}

Run command on pod in a cluster

kubectl exec -ti {pod_name}

Display pod status

kubectl describe pod {deployment_name}

Get shell to a pod

kubectl exec --stdin --tty {deployment_name} -- /bin/bash

Execute command on pod

docker exec {deployment_name} {command_text}

Show resource labels

kubectl get {resource_name} --show-labels

Stop deployment in a Kubernetes pod

kubectl scale --replicas=0 {deployment_name}

Get all deployments in namespace

kubectl get deployment -n {namespace_name}

Web API Security Considerations for ASP.NET Web API

Avoid Revealing Software Version Numbers

Although this information may seem innocuous, it allows an attacker to identify the version of server side components and therefore target further attacks to this specific software. This can quickly lead to successful exploitation if the server side components have vulnerabilities with publicly available exploit code. The server software versions used by the application are revealed by the web server. Displaying version information of software information could allow an attacker to determine which vulnerabilities are present in the software, particularly if an outdated software version is in use with published vulnerabilities.

See the following guide for removing the headers from IIS and ASP.NET: https://blogs.msdn.microsoft.com/varunm/2013/04/23/removeunwanted-http-response-headers

Avoid Information Disclosure via Verbose Error Messages

It is recommended that functionality is implemented within the application that detects when an error has occurred and redirects the user to a custom error page that does not disclose any form of sensitive data. These errors that should induce a redirect to a custom error page should include 403 Forbidden Errors – to prevent an adversary from enumerating existing pages on the application that require prior authentication to view; 404 Not Found pages; and 500 Internal Error pages. Alternatively, simply redirecting a user to the applications home page can also suffice in reducing the level of information disclosed.

For ASP.NET, in web.config set one of the following options: 

<customErrors mode="RemoteOnly" />
<customErrors mode="On" />

Write out Security Headers

A number of HTTP Security Headers have been introduced in recent years to enhance security of a website by providing protections against certain types of attacks. The following table contains the headers which fall under this vulnerability category, notes are offered in the technical analysis as to which headers are missing and any misconfiguration discovered during the engagement.

It’s strongly recommended that these headers are configured on all applications to further harden the application from attack.

Few example headers that should be used:

  • Strict-Transport-Security – HTTP Strict-Transport-Security (HSTS) enforces secure (HTTP over SSL/TLS) connections to the server. This reduces impact of bugs in web applications leaking session data through cookies and external links and defends against Man-in-the-Middle attacks. HSTS also disables the ability for users to ignore SSL negotiation warnings
  • X-Frame-Options – improves the protection of web applications against Clickjacking. It declares a policy communicated from a host to the client browser on whether the browser must not display the transmitted content in frames of other web pages. This functionality can also be achieved with Content-Security-Policy.
  • X-XSS-Protection – enables the Cross-Site Scripting (XSS) filter that is built into most modern web browsers. Typically, the filter is enabled by default; the role of this header is to re-enable the filter if it was disabled by the user and also sets blocking mode which can mitigate some filter bypasses.
  • X-Content-Type-Options – The only defined value, “nosniff”, prevents Internet Explorer and Google Chrome from MIME-sniffing a response away from the declared content-type. This reduces exposure to cross-site scripting vulnerabilities that may not otherwise be present.
  • Content-Security-Policy – requires careful tuning and precise definition of the policy. If enabled, CSP has significant impact on the way browser renders pages (e.g., inline JavaScript disabled by default and must be explicitly allowed in policy). CSP prevents a wide range of attacks, including Cross-Site Scripting and other Cross-Site Injections.
  • Referrer-Policy – governs which referrer information, sent in the Referer header, should be included with requests made.

Additional information, plus examples of all headers to consider can be found at https://securityheaders.com

Use Cross-Site Request Forgery Protection

Cross-Site Request Forgery (CSRF) vulnerabilities arise when applications rely solely on HTTP cookies to identify the user that has issued a particular request. Because browsers automatically add cookies to requests regardless of their origin, it may be possible for an attacker to create a malicious web site that forges a cross-domain request to the vulnerable application. For a request to be vulnerable to CSRF, the following conditions must hold:

  • The request must be issued cross-domain, for example using an HTML form. If the request contains non-standard headers or body content and these are checked server-side, then it may only be issuable from a page that originated on the same domain.
  • The application must rely solely on HTTP cookies or Basic Authentication to identify the user that issued the request. If the application places session-related tokens within the request body, then it may not be vulnerable.
  • The request performs a privileged action within the application based on the identity of the issuing user.
  • The attacker can determine all the parameters required to construct a request that performs the action. If the request contains values that the attacker cannot determine or predict, then it is not vulnerable.

The most effective way to protect against CSRF vulnerabilities is to include within relevant requests an additional token that is not transmitted in a cookie: for example, a parameter in a hidden form field. This additional token should be random enough such that it is not feasible for an attacker to determine or predict the value of any token that was issued to another user. The token should be associated with the user’s session, and the application should validate that the correct token is received before performing any action resulting from the request.

An alternative approach, which may be easier to implement, is to validate that Host and Referer headers in relevant requests are both present and contain the same valid domain name. The Origin header can also be validated against the Host, however some browsers do not support this for requests made from the same domain, therefore this mechanism would need to use the Referer header as a fallback. For AJAX requests, a custom header can be added and then checked server-side (e.g. “X-Requested-With: XMLHttpRequest”), because this cannot be passed cross-domain without CORS being enabled.

However, these header checking approaches are somewhat less robust. Historically, quirks in browsers and implementation errors have often enabled attackers to forge cross-domain requests that manipulate these headers to bypass such defence.

How to check which port is used by a particular process/application on Windows

To find the process ID (PID) of the application, we need to run following command:

tasklist | findstr '<application/process name>

This will display all processes running on machine, where process name contains <application/process name> value. Result of above command includes PID – we will use this in next step.

Next, we run below command to find actual port number used by the process:

netstat -ano | findstr <PID>

This command lists all ports used by process.

Semantic versioning

This is an excerpt from ASP.NET Core documentation on semantic versioning. The full document can be found here

The .NET Core Runtime roughly adheres to Semantic Versioning (SemVer), adopting the use of MAJOR.MINOR.PATCH versioning, using the various parts of the version number to describe the degree and type of change.Copy

MAJOR.MINOR.PATCH[-PRERELEASE-BUILDNUMBER]

The optional PRERELEASE and BUILDNUMBER parts are never part of supported releases and only exist on nightly builds, local builds from source targets, and unsupported preview releases.

Understand runtime version number changes

MAJOR is incremented when:

  • Significant changes occur to the product, or a new product direction.
  • Breaking changes were taken. There’s a high bar to accepting breaking changes.
  • An old version is no longer supported.
  • A newer MAJOR version of an existing dependency is adopted.

MINOR is incremented when:

  • Public API surface area is added.
  • A new behavior is added.
  • A newer MINOR version of an existing dependency is adopted.
  • A new dependency is introduced.

PATCH is incremented when:

  • Bug fixes are made.
  • Support for a newer platform is added.
  • A newer PATCH version of an existing dependency is adopted.
  • Any other change doesn’t fit one of the previous cases.

When there are multiple changes, the highest element affected by individual changes is incremented, and the following ones are reset to zero. For example, when MAJOR is incremented, MINOR and PATCH are reset to zero. When MINOR is incremented, PATCH is reset to zero while MAJOR is left untouched.

Windows command line aliases

In this article I’ll walk through creating alias in Windows command line. I will create alias named “subl” for launching Sublime Text 3 editor from command line.

For this purpose, doskey command is particularly useful.

Sublime Text 3 is installed in default folder on my PC, so running below command will do the trick:

doskey subl="C:\Program Files\Sublime Text 3\sublime_text.exe"

Now I can type

subl

in command prompt and system starts Sublime Text 3 editor.

There is one little catch here though. Even if I type

subl C:\tmp\file.txt

Sublime always opens new blank document.

In order to be able to pass parameter into the alias, doskey command needs to be altered slightly:

doskey subl="C:\Program Files\Sublime Text 3\sublime_text.exe" $*

Adding “$*” at the end allows the alias to accept zero, one, or more args.

I can now type

subl C:\tmp\file.txt

and Sublime happily loads correct file.

Gotcha!

While using this alias, I discovered one very annoying thing: aliases disappear when console is restarted. Doskey command needs to be called again.

There is a way to automate loading Doskey macros (loads of information on this on google), but it requires modifying Windows registry, which I did not want.

Instead I found easier solution:

I created very simple batch file called subl.bat:

@ECHO OFF

START "" "C:\Program Files\Sublime Text 3\sublime_text.exe" %1

And moved it to location listed in system PATH variable, i.e. %USERPROFILE%

Now calling

subl \tmp\path.txt

Launches new instance of Sublime Text even after restarting console.

Voila!

Developer’s Interview Questions

This is post is not meant to be another iteration of “most common questions you will be asked when applying for dev role”. It’s the opposite – it’s about questions you will want to ask your potential employer before you commit yourself any further. The biggest mistake we tend to do when sitting interview is not evaluating employer well enough in order to make informed decision.

  1. Are all builds handled automatically by a Continuous Integration server?
  2. Do you make and use daily builds?
  3. Do you use an issue tracker?
  4. Do you fix bugs before writing new code?
  5. Do you have an up-to-date schedule?
  6. Do you have up to date information on your products performance and usage?
  7. Do you use the best tools money can buy?
  8. Do you have a comprehensive test plan?
  9. Do you have dedicated UI and UX designers?
  10. Does all code go through code review?
  11. Do you have coding standards?
  12. Are new employees given training?

Source:
https://myers.io/2017/04/04/the-joel-test-for-2017/

AD FS – what, why and how?

Excellent article by Sean Ivey from Microsoft on what’s good (and what’s no so much) about AD FS:

https://blogs.technet.microsoft.com/askidentity/2013/05/13/an-introduction-to-ad-fs-we-can-all-understand/

Further read on the subject:

https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/ee913566(v=ws.10)

Generate SSH Key Pair in Linux

Following command creates SSH key pair:

ssh-keygen

It will then prompt you for the location (the default ~/.ssh/id_rsa) and for a passphrase. The result will be two files, id_rsa (the private key) and id_rsa.pub (the public key). The public key will be store on this server while the private key will be copied into the client.

More details can be found here

Following command needs to be run on the server to push generated public key to SSH key repo:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

This will append newly generated public key to existing authorized keys.

Finally appropriate permissions need to be set on the server:

chmod 600 ~/.ssh/authorized_keys

More details on SSH configuration can be found here