Category

Cloud Assessment

Detect highly distributed web DDoS on CloudFront, from botnets

By | Blogs, Cloud, Cloud Assessment | No Comments

Author: Niraj Kumar Gupta, Cloud Consulting at Powerupcloud Technologies.

Contributors: Mudit Jain, Hemant Kumar R and Tiriveedi Srividhya

INTRODUCTION TO SERVICES USED

 CloudWatch Metrics

Metrics are abstract data points indicating performance of your systems. By default, several AWS services provide free metrics for resources (such as Amazon EC2 instances, Amazon EBS volumes, and Amazon RDS DB instances).

CloudWatch Alarms

AWS CloudWatch Alarm is a powerful service provided by Amazon for monitoring and managing our AWS services. It provides us with data and actionable insights that we can use to monitor our application/websites, understand and respond to critical changes, optimize resource utilization, and get a consolidated view of the entire account. CloudWatch collects monitoring and operational information in the form of logs, metrics, and events. You can configure alarms to initiate an action when a condition is satisfied, like reaching a pre-configured threshold.

CloudWatch Dashboard

Amazon CloudWatch Dashboards is a feature of AWS CloudWatch that offers basic monitoring home pages for your AWS accounts. It provides resource status and performance views via graphs and gauges. Dashboards can monitor resources in multiple AWS regions to present a cohesive account-wide view of your accounts.

CloudWatch Composite Alarms

Composite alarms enhance existing alarm capability giving customers a way to logically combine multiple alarms. A single infrastructure event may generate multiple alarms, and the volume of alarms can overwhelm operators or mislead the triage and diagnosis process. If this happens, operators can end up dealing with alarm fatigue or waste time reviewing a large number of alarms to identify the root cause. Composite alarms give operators the ability to add logic and group alarms into a single high-level alarm, which is triggered when the underlying conditions are met. This gives operators the ability to make intelligent decisions and reduces the time to detect, diagnose, and performance issues when it happen.

What are Anomaly detection-based alarms?

Amazon CloudWatch Anomaly Detection applies machine-learning algorithms to continuously analyze system and application metrics, determine a normal baseline, and surface anomalies with minimal user intervention. You can use Anomaly Detection to isolate and troubleshoot unexpected changes in your metric behavior.

Why Composite Alarms?

  1. Simple Alarms monitor single metrics. Most of the alarms triggered, limited by the design, will be false positives on further triage. This adds to maintenance overhead and noise.
  2. Advance use cases cannot be conceptualized and achieved with simple alarms.

Why Anomaly Detection?

  1. Static alarms trigger based on fixed higher and/or lower limits. There is no direct way to change these limits based on the day of the month, day of the week and/or time of the day etc. For most businesses these values change massively over different times of the day and so on. Specially so, while monitoring user behavior impacted metrics, like incoming or outgoing traffic. This leaves the static alarms futile for most of the time. 
  2. It is cheap AI based regression on the metrics.

Solution Overview

  1. Request count > monitored by anomaly detection based Alarm1.
  2. Cache hit > monitored by anomaly detection based Alarm2.
  3. Alarm1 and Alarm2 > monitored by composite Alarm3.
  4. Alarm3 > Send Notification(s) to SNS2, which has lambda endpoint as subscription.
  5. Lambda Function > Sends custom notification with CloudWatch Dashboard link to the distribution lists subscribed in SNS1.

Solution

Prerequisites

  1. Enable additional CloudFront Cache-Hit metrics.

Configuration

This is applicable to all enterprise’s CloudFront CDN distributions.

  1. We will configure an Anomaly Detection alarm on request count increasing by 10%(example) of expected average.

2. We will add an Anomaly Detection alarm on CacheHitRate percentage going lower than standard deviation of 10%(example) of expected average.

3. We will create a composite alarm for the above-mentioned alarms using logical AND operation.

4. Create a CloudWatch Dashboard with all required information in one place for quick access.

5. Create a lambda function:

This will be triggered by SNS2 (SNS topic) when the composite alarm state changes to “ALARM”. This lambda function will execute to send custom notifications (EMAIL alerts) to the users via SNS1 (SNS topic)

The target arn should be the SNS1, where the user’s Email id is configured as endpoints.

In the message section type the custom message which needs to be notified to the user, here we have mentioned the CloudWatch dashboard URL.

6. Create two SNS topics:

  • SNS1 – With EMAIL alerts to users [preferably to email distribution list(s)].
  • SNS2 – A Lambda function subscription with code sending custom notifications via SNS1 with links to CloudWatch dashboard(s). Same lambda can be used to pick different dashboard links based on the specific composite alarm triggered, from a DynamoDB table with mapping between SNS target topic ARN to CloudWatch Dashboard link.

7. Add notification to the composite alarm to send notification on the SNS2.

Possible False Positives

  1. There is some new promotion activity and the newly developed pages for the promotional activity.
  2. Some hotfix went wrong at the time of spikes in traffic.

Summary

This is one example of implementing a simple setup of composite alarms and anomaly-based detection alarms to achieve advance security monitoring. We are submitting the case that these are very powerful tools and can be used to design a lot of advanced functionalities.

Handling Asynchronous Workflow-Driven pipeline with AWS CodePipeline and AWS Lambda

By | AWS, Blogs, Cloud, Cloud Assessment, Data pipeline | No Comments

Written by Praful Tamrakar Senior Cloud Engineer, Powerupcloud Technologies

Most of the AWS customers use AWS lambda widely for performing almost every task, especially its a very handy tool when it comes to customizing the way your pipeline works. If we are talking about pipelines, then AWS Lambda is a service that can be directly integrated with AWS CodePipeline. And the combination of these two services make it possible for AWS customers to successfully automate various tasks, including infrastructure provisioning, blue/green deployments, serverless deployments, AMI baking, database provisioning, and deal with asynchronous behavior.

Problem Statement :

Our customer has a requirement to trigger and monitor the status of the Step Function state machine, which is a long-running asynchronous process. The customer is using the AWS Step Function to run the ETL jobs with the help of AWS Glue jobs and AWS EMR. We proposed to achieve this with Lambda but lambda has a limitation of its timeout i.e. 15 min. Now the real problem is that such an asynchronous process needs to continue and succeed even if it exceeds a fifteen-minute runtime (a limit in Lambda).

Here in this blog we have a solution in which we have figured out how we can solve and automate this approach, with the combination of lambda and AWS CodePipeline with Continuous token.

Assumptions :

This blog assumes you are familiar with AWS CodePipeline and AWS Lambda and know how to create pipelines, functions, Glue jobs and the IAM policies and roles on which they depend.

Pre-requisites:

  1. Glue jobs has already been configured
  2. A StepFunction StateMachine configured to run  Glue Jobs.
  3. CodeCommit repository for Glue scripts

Solution :

In this blog post, we discuss how a CodePipeline action can trigger a Step Functions state machine and how the pipeline and the state machine are kept decoupled through a Lambda function.

The source code for the sample pipeline, pipeline actions, and state machine used in this post is available at https://github.com/powerupcloud/lambdacodepipeline.git.

The below diagram highlights the CodePipeline-StepFunctions integration that will be described in this post. The pipeline contains two stages: a Source stage represented by a CodeCommit Git repository and a DEV stage with CodeCommit, CodeBuild and Invoke Lambda actions that represent the workflow-driven action.

The Steps involved  in the CI/CD pipeline:

  1. Developers commit AWS Glue job’s Code in the SVC (AWS CodeCommit)
  2. The AWS CodePipeline in the Tools Account gets triggered due to step
  3. The Code build steps involve multiple things as mentioned below
    • Installations of dependencies and packages needed
    • Copying the Glue and EMR jobs to S3 location where the Glue jobs will pick the script from.
  4. CHECK_OLD_SFN: The Lambda is invoked to ensure that the Previous Step function execution is not still in a running state before we run the actual Step function. Please find below the process.
    • This action invokes a Lambda function (1).
    • In (2) Lamba Checks the State Machine  Status, which returns a Step Functions State Machine status.
    • In (3) The lambda gets the execution state of the State Machine ( RUNNING || COMPLETED || TIMEOUT )
    • In (4) The Lambda function sends a continuation token back to the pipeline

If The State Machine State is RUNNING in Seconds later, the pipeline invokes the Lambda function again (4), passing the continuation token received. The Lambda function checks the execution state of the state machine and communicates the status to the pipeline. The process is repeated until the state machine execution is complete.

Else (5) Lambda  sends a Job completion token  and completes the pipeline stage.

  1.  TRIGGER_SFN_and_CONTINUE : Invoking Lambda to execute the new Step function execution and Check the status of the new execution. Please find below the process.
    • This action invokes a Lambda function (1) called the State Machine, which, in turn, triggers a Step Functions State Machine to process the request (2).
    • The Lambda function sends a continuation token back to the pipeline (3) to continue its execution later and terminates.
    • Seconds later, the pipeline invokes the Lambda function again (4), passing the continuation token received. The Lambda function checks the execution state of the state machine (5,6) and communicates the status to the pipeline. The process is repeated until the state machine execution is complete.
    • Then the Lambda function notifies the pipeline that the corresponding pipeline action is complete (7). If the state machine has failed, the Lambda function will then fail the pipeline action and stop its execution (7). While running, the state machine triggers various Glue Jobs to perform ETL operations. The state machine and the pipeline are fully decoupled. Their interaction is handled by the Lambda function.
  2. Approval to the Higher Environment. In this stage, we Add a Manual Approval Action to a Pipeline in CodePipeline. Which can be implemented using https://docs.aws.amazon.com/codepipeline/latest/userguide/approvals-action-add.html

Deployment Steps :

Step 1: Create a Pipeline

  1. Sign in to the AWS Management Console and open the CodePipeline console at http://console.aws.amazon.com/codesuite/codepipeline/home.
  2. On the Welcome page, Getting started page, or the Pipelines page, choose Create pipeline.
  3. In Choose pipeline settings, in Pipeline name, enter the pipeline name.
  4. In-Service role, do one of the following:
    • Choose a New service role to allow CodePipeline to create a new service role in IAM.
    • Choose the Existing service role to use a service role already created in IAM. In Role name, choose your service role from the list.
  5. Leave the settings under Advanced settings at their defaults, and then choose Next.

6. In the Add source stage, in Source provider, Choose Source Provider as CodeCommit.

7. Provide Repository name and Branch Name

8. In Change detection options Choose AWS CodePipeline

9. In Add build stage,  in Build provider choose AWS CodeBuild, choose the Region

10. Select the existing Project name or Create project

11. You Can add Environment Variables, which you may use in buildspec.yaml file , and click Next

NOTE: The build Step has a very special reason. Here we copy the glue script from SVC (AWS CodeCommit ) to the S3 bucket, from where the Glue job picks its script to execute in its next execution.

12. Add deploy stage, Skip deploy Stage.

13. Now Finally click Create Pipeline.

Step 2: Create the CHECK OLD SFN LAMBDA Lambda Function

  1. Create the execution role
  • Sign in to the AWS Management Console and open the IAM console

Choose Policies, and then choose Create Policy. Choose the JSON tab, and then paste the following policy into the field.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "states:*",
                "codepipeline:PutJobFailureResult",
                "codepipeline:PutJobSuccessResult"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "logs:*",
            "Resource": "arn:aws:logs:*:*:*"
        }
    ]
}
  • Choose Review policy.
  • On the Review policy page, in Name, type a name for the policy (for example, CodePipelineLambdaExecPolicy). In Description, enter Enables Lambda to execute code.
  • Choose Create Policy.
  • On the policy dashboard page, choose Roles, and then choose to Create role.
  • On the Create role page, choose AWS service. Choose Lambda, and then choose Next: Permissions.
  • On the Attach permissions policies page, select the checkbox next to CodePipelineLambdaExecPolicy, and then choose Next: Tags. Choose Next: Review.
  • On the Review page, in Role name, enter the name, and then choose to Create role.

2. Create the CHECK_OLD_SFN_LAMBDA Lambda function to use with CodePipeline

  • Open the Lambda console and choose the Create function.
  • On the Create function page, choose Author from scratch. In the Function name, enter a name for your Lambda function (for example, CHECK_OLD_SFN_LAMBDA ) .
  • In Runtime, choose Python 2.7.
  • Under Role, select Choose an existing role. In Existing role, choose your role you created earlier, and then choose the Create function.
  • The detail page for your created function opens.
  • Copy the check_StepFunction.py code into the Function code box
  • In Basic settings, for Timeout, replace the default of 3 seconds with 5 Min.
  • Choose Save.

3. Create the TRIGGER_SFN_and_CONTINUE Lambda function to use with CodePipeline

  • Open the Lambda console and choose the Create function.
  • On the Create function page, choose Author from scratch. In Function name, enter a name for your Lambda function (for example, TRIGGER_SFN_and_CONTINUE ) .
  • In Runtime, choose Python 2.7.
  • Under Role, select Choose an existing role. In Existing role, choose your role you created earlier, and then choose the Create function.
  • The detail page for your created function opens.
  • Copy the trigger_StepFunction.py code into the Function code box
  • In Basic settings, for Timeout, replace the default of 3 seconds with 5 Min.
  • Choose Save.

Step 3: Add the CHECK OLD SFN LAMBDA, Lambda Function to a Pipeline in the CodePipeline Console

In this step, you add a new stage to your pipeline, and then add a Lambda action that calls your function to that stage.

To add stage

  • Sign in to the AWS Management Console and open the CodePipeline console at http://console.aws.amazon.com/codesuite/codepipeline/home.
  • On the Welcome page, choose the pipeline you created.
  • On the pipeline view page, choose Edit.
  • On the Edit page, choose + Add stage to add a stage after the Build stage with thaction. Enter a name for the stage (for example, CHECK_OLD_SFN_LAMBDA ), and choose Add stage.
  • Choose + Add action group. In Edit action, in Action name, enter a name for your Lambda action (for example, CHECK_OLD_SFN_LAMBDA ). In Provider, choose AWS Lambda. In Function name, choose or enter the name of your Lambda function (for example, CHECK_OLD_SFN_LAMBDA )
  • In UserParameters, you must provide a JSON string with a parameter: { “stateMachineARN”: “<ARN_OF_STATE_MACHINE>” } EG: 
  • choose Save.

Step 4: Add the TRIGGER_SFN_and_CONTINUE  Lambda Function to a Pipeline in the CodePipeline Console

In this step, you add a new stage to your pipeline, and then add a Lambda action that calls your function to that stage.

To add a stage

  • Sign in to the AWS Management Console and open the CodePipeline console at http://console.aws.amazon.com/codesuite/codepipeline/home.
  • On the Welcome page, choose the pipeline you created.
  • On the pipeline view page, choose Edit.
  • On the Edit page, choose + Add stage to add a stage after the Build stage with thaction. Enter a name for the stage (for example, TRIGGER_SFN_and_CONTINUE ), and choose Add stage.
  • Choose + Add action group. In Edit action, in Action name, enter a name for your Lambda action (for example, TRIGGER_SFN_and_CONTINUE ). In Provider, choose AWS Lambda. In Function name, choose or enter the name of your Lambda function (for example, TRIGGER_SFN_and_CONTINUE )
  • In UserParameters, you must provide a JSON string with a parameter: { “stateMachineARN”: “<ARN_OF_STATE_MACHINE>” }
  • choose Save.

Step 5: Test the Pipeline with the Lambda function

  • To test the function, release the most recent change through the pipeline.
  • To use the console to run the most recent version of an artifact through a pipeline
  • On the pipeline details page, choose Release change. This runs the most recent revision available in each source location specified in a source action through the pipeline.
  • When the Lambda action is complete, choose the Details link to view the log stream for the function in Amazon CloudWatch, including the billed duration of the event. If the function failed, the CloudWatch log provides information about the cause.

Example JSON Event

The following example shows a sample JSON event sent to Lambda by CodePipeline. The structure of this event is similar to the response to the GetJobDetails API, but without the actionTypeId and pipelineContext data types. Two action configuration details, FunctionName and UserParameters, are included in both the JSON event and the response to the GetJobDetails API. The values in green text are examples or explanations, not real values.

{
    "CodePipeline.job": {
        "id": "11111111-abcd-1111-abcd-111111abcdef",
        "accountId": "111111111111",
        "data": {
            "actionConfiguration": {
                "configuration": {
                    "FunctionName": "MyLambdaFunctionForAWSCodePipeline",
                    "UserParameters": "some-input-such-as-a-URL"
                }
            },
            "inputArtifacts": [
                {
                    "location": {
                        "s3Location": {
                            "bucketName": "s3-bucket-name",
                            "objectKey": "for example CodePipelineDemoApplication.zip"
                        },
                        "type": "S3"
                    },
                    "revision": null,
                    "name": "ArtifactName"
                }
            ],
            "outputArtifacts": [],
            "artifactCredentials": {
                "secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
                "sessionToken": "MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w
0BAQUFADCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTbNYiytVbZPQUQ5Yaxu2jXnimvwdasdadasljdajldlakslkdjakjdkaljdaljdasljdaljdalklakkoi9494k3k3owlkeroieowiruwpirpdk3k23j2jk234hjl2343rrszlaEXAMPLE=",
                "accessKeyId": "AKIAIOSFODNN7EXAMPLE"
            },
            "continuationToken": "A continuation token if continuing job",
            "encryptionKey": { 
              "id": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
              "type": "KMS"
            }
        }
    }
}

Conclusion

In this blog post, we discussed how a Lambda function can be used fully to decouple the pipeline and the state machine and manage their interaction. We also learned how asynchronous processes that need to continue and succeed, even if it exceeds a fifteen-minute runtime (a limit in Lambda) are handled using Continuous Token.

Please Visit our Blogs for more interesting articles.

11-Point Cloud Plan To Tackle The Covid-19 Economy

By | Cloud, Cloud Assessment, News | No Comments

Siva S Founder & CEO – Powerupcloud Technologies

The Covid-19 virus pandemic has changed a lot of things forever or at least that should be our best assumption now. As Sequoia quotes, this is the Black Swan of 2020 which may very well extend into most of 2021. While some are still trying to understand the impact this will have on the global economy, we need to make up our minds and accept that this is here to stay for a longer period. I find a lot of merit in the endgame possibilities of the Covid-19 virus highlighted in an article by The Atlantic. Of the 3 possible endgame scenarios, the best option sounds like this – “the world plays a protracted game of whack-a-mole with the virus, stamping out outbreaks here and there until a vaccine can be produced.”

As the CEO of Powerupcloud – a global leader in cloud consulting space and the global cloud practice head of LTI – one of the largest technology solutions and services providers in the world, I interact with several CIOs, Business Leaders, and Technologists on a daily basis and I am privy to the thought process and technology decisions being made by these global enterprise businesses in this period of volatility.

Having strategic conversations with more than 50 top CEOs, CIOs, Business Leaders of Fortune500 companies and public cloud OEMs, I am convinced that at no other point in time has there ever been such a need for the instant availability of technology than now. And the public cloud has emerged as the biggest enabler during these uncertain times. If you are an organization that is still considering the move to the cloud, stop procrastinating and start your cloud adoption process immediately. With the fast-changing economic scenario, you need to act fast and act now.

The 11-Point Cloud Plan for Covid-19 Pandemic Economy

 

These discussions with CIOs and Cloud Leaders have helped me to build the 11-Point Cloud Plan on how enterprises should prioritize and execute their cloud adoption & optimization plan over the next 3 months (ultra short term) and the next 12 months (short term). This is not the time for drafting a 3-year or a 5-year plan as we are not sure of the outcome even after the next 12 months. And if you are in the middle of executing such plans, please stop and revisit your priorities immediately.

The 11-Point Cloud Plan has 3 purpose tracks.

A. Business Continuity Planning

B. Cost Savings on Cloud

C. Short Term Cloud Initiatives

A. BUSINESS CONTINUITY PLANNING

With more and more enterprises moving to a remote working model where employees connect from home, I see that a good amount these businesses are grappling with a viable business continuity design which will allow them to continue their operations. Remember, keeping your business moving is the best outcome the world economy needs today.

There are 5 key areas which the organizations are adopting on the cloud to support their business continuity. I have prioritized them based on the feedback we received from the market.

  1. Virtual Contact Center on Cloud – Employees doing ‘work from home’ are struggling with their traditional contact center software which doesn’t allow them to answer customer support calls effectively. Cloud-based Amazon Connect allows you to bring up a virtual contact center in just 45 minutes and with an additional 8 hours effort, you can also automate the customer care responses by integrating Amazon AI services like Amazon Lex & Amazon Polly.
  2. Virtual Desktops on Cloud – Another major request coming in from companies with remote employees is the virtual desktop solution. Both Microsoft Azure’s Windows Virtual Desktop and Amazon Workspaces are sought after technology offerings on the cloud which solves this problem. You can launch these virtual desktop solutions using automated templates for 1000s of employees in matter of hours.
  3. Support Chatbots on Cloud – Be it customer support or internal employee support, there is no better time to be proactive in responding to their queries. Chatbots enables an organization to route at least 50% of the customer queries away from customer support agents. Cloud technologies like Google Cloud’s DialogFlow, Amazon Lex, Amazon Polly, Microsoft Bot FrameworkAzure QnA Maker, Microsoft Luis helps in designing your chatbots. Powerup’s Botzer platform also helps you in integrating with the above-mentioned cloud APIs and launch & manage your chatbots in a day.
  4. Risk Modeling on Cloud – Several organizations in industries like Insurance, Stock Trading, Banking, Pharma, Life Sciences, Retail, FMCG are running their risk modeling algorithms on an almost daily basis to reassess their risk in the current market scenario. This requires additional compute power (Amazon EMRAzure HDInsightGoogle Dataproc and machine learning platforms (Google Cloud AutoMLAmazon SagemakerAzureML) on the cloud.
  5. Governance & Security on Cloud – For organizations with a lot of applications on cloud, governance, and security becomes a tricky part to handle given that most of their employees are connecting from home. Cloud Governance Products like Powerup’s CloudEnsure.io helps organizations to enforce a zero-trust security model across their multi-cloud environments and ensures that the security vulnerabilities are addressed in real-time.

B. COST SAVINGS ON CLOUD

6. Cost Optimization on Cloud – We will witness a spending crunch by a lot of organizations across industries and IT departments in these organizations will come under severe pressure to reduce their cloud costs. From our experience in helping a lot of organizations reduce their cloud spend, I have identified 6 key methods using which you can save cloud costs.

  • Downsize your cloud resources and plan your cloud inventory to the bare minimum that is required to run your business.
  • Shutdown unused cloud resources and free up storage & network. This might require you to revisit your new initiatives and data retention policies.
  • Adopt reserved instances pricing model for a 1-year or 3-year period which will allow you to save up to 60% on your compute spend.
  • Explore spot instances for at least 50% of your cloud workloads which will help you reduce your cloud spend by 80% for the workloads where spot instances are enabled.
  • Explore containerization for a minimum 1/3rd of your large applications on the cloud which will help you save up to 75% on your compute spend.
  • Schedule your non-production instances/servers to start and stop on a daily basis which can help you save almost 50% of your server compute bills.
  • Intelligent tiering of objects stored on Amazon S3 or Azure Blob to lower storage tiers will help you save a lot of storage costs. Amazon S3 Intelligent Tiering and Azure’s Archival/Cold storage options can be leveraged to save costs.
  • Explore the possibilities of moving some of the workloads to other cloud platforms where variable pricing is possible. This can also help you save costs. For eg: some companies leverage flexible hardware configuration options of Google Cloud.
  • Migrate your applications and databases from enterprise licensed platforms to open-source platforms. Eg: migrating from Redhat Linux to Amazon Linux or from Oracle database to PostgreSQL.
  • Finally, it comes to the good old Excel sheets. The old school way of analyzing cloud usage and billing data by experienced cloud architects cannot be matched by cloud cost analytics tools. Roll up your sleeves and get your hands dirty if it comes to that.

Powerup’s CloudEnsure.io has tailored modules that help organizations track their cloud spend by departments, applications, users, etc and help them with a detailed (resource level) cost optimization plan for their cloud environment.

C. SHORT TERM CLOUD INITIATIVES

Now that the long-term initiatives by organizations will go under the scanner and potentially recalibrated to suit the larger financial goal of the organization, there are still a lot of things that the organizations can do in the short-term to help them prepare themselves for the next 12-18 months. These ‘Short Term Initiatives’ are designed to help you make measured but important progress in your cloud adoption journey and will fit very well into your long-term plan when the situation gets better.

I have listed 5 key short-term initiatives that are being adopted by several medium and large enterprises across industries globally.

7. Data Lake on Cloud – It is during these times, several organizations realize that they don’t have enough hold on their data to make some critical business decisions. They see that their data is spread across various applications, in various formats and in various database technologies which restricts them from correlating the data and gain valuable insights. A centralized Data Lake on the cloud solves this problem. You can launch a full-fledged Data Lake that can be built in less than 60 days using cloud-native data lake technologies (Amazon Redshift, Azure DataLake) or some leading 3rd party data platforms like Snowflake or Databricks. It is the best time to start building your organization’s central data lake on the cloud if you don’t have one.

8. Fast-Track Application Development on Cloud – These uncertain times requires organizations to try new business models and introduce new processes to handle their business. I see large banks building specialized apps for payment holidays on buy-to-let mortgages in record time. And I am sure you might have similar requirements for building specialized workflow-based apps. Cloud is the best place to build these apps in a very short period of time and if you use serverless functions like Amazon Lambda, Microsoft Functions, it will help in less overhead in managing the availability of these apps. Please remember, managerial bandwidth is super key in the coming days and you should plan to free up your employees’ time for high priority tasks.

9. Outsource Cloud Managed Services – Cloud support or managed services is a human capital intensive division of IT departments and it is the right time to outsource the managed services scope to cloud partners like Powerup who can deliver the cloud support in a shared capacity model. This would greatly reduce your human capital overhead cost in managing your cloud environment.

10. Move Critical Applications to Cloud – Large scale enterprise data center migrations will help you to move to an OPEX model and reduces the stress on the cash flow which is highly recommended given the volatile economic outlook for the next 2 years. But the best way to begin this is by looking at your business-critical applications and migrate them to the cloud. This will allow you to migrate in a phased manner to the cloud within the next 12 months. Please don’t consider the big-bang cloud migration approach for the next 12 months. Conserving cash and spending them in a planned manner is going to be key for any business to survive.

11. DevOps Automation on Cloud – DevOps process automation is another key aspect that the companies are executing to reduce the dependency on their technical resources. ‘Work from home’ model has its own challenges w.r.to coordination, network connectivity, etc which leads to highly delayed DevOps deployments. This might be the right time for you to look at automating your DevOps process for your applications running on the cloud or in your on-premise setup.

Conclusion

Like I mentioned earlier, the 11-Point Cloud Plan was devised based on the market observations and feedback from our global enterprise customers. Will the plan change in the near term? Absolutely Yes. But for now, this seems to be the best bet for us. This 11-Point Cloud Plan should get you started thinking/acting in the right direction and trust me this will help you follow the footsteps of several leading organizations in today’s economic scenario caused by Covid-19 pandemic. The plan will continue to evolve and I will keep this updated as I learn more from our partners and customers.

Stay safe with your loved ones.

Take care of the community around you.

And keep the business rolling.

 

Securing Spring Boot and React JS with Spring Security using JWT authentication

By | Blogs, Cloud, Cloud Assessment | One Comment

Written by Kiran M D Software Engineer – Powerupcloud Technologies

This article helps you set up Spring Security with Basic and JWT authentication with a full-stack application using React Js as Frontend framework and Spring Boot as the backend REST API.

Let’s understand what is the use of JWT Token and how we are going to use it in our application

JSON Web Token

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.

How does it work? 

In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned. Since the tokens are credentials, we must prevent security bugs/breaches. In general, you should not keep tokens longer than required.

Whenever the user wants to access a protected route or resource, the user agent should send the JWT, typically in the Authorization header using the Bearer schema. The content of the header should look like the following:

Sample JSON:

{

“Authorization”: “Bearer <token>”

}

Lets see how can we integrate with Springboot and React JS.

1. Creating spring boot application and configuring JWT authentication.

1.1 Creating a sample spring boot application

Basic spring boot application can be generated using spring initializer with the following dependencies.

1.Spring web

2.spring security

Open the Spring initializer URL and add above dependency

Spring Boot REST API Project Structure

Following screenshot shows the structure of the Spring Boot project, we can create a Basic Authentication.

1.2 Add the below dependency in Pom.xml for JWT token.

<dependency>
	<groupId>io.jsonwebtoken</groupId>
	<artifactId>jjwt</artifactId>
	<version>0.9.1</version>
</dependency>
		
<dependency>
           <groupId>org.json</groupId>
           <artifactId>json</artifactId>
           <version>20180813</version>
 </dependency>

1.3 Create the following files in config package.

JwtAuthenticationEntryPoint.java

The purpose of this file is to handle exceptions and whenever JWT  token is not validated it throws Unauthorised exception.

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable
{
    @Override
    public void commence(HttpServletRequest request, 
	HttpServletResponse response,
	AuthenticationException authException) throws IOException 
    {
	response.sendError(HttpServletResponse.SC_UNAUTHORIZED,         "Unauthorized");
    }
}

JwtRequestFilter.java

The purpose of this file is to handle filtering the request from the client-side or react js, here is where all the request will come first before hitting the rest API, if the token validation is successful then actual API gets a request.

@Component
@Component
public class JwtRequestFilter extends OncePerRequestFilter 
{
	
	@Autowired
	private JwtUserDetailsService jwtUserDetailsService;
	
	
      @Autowired
	private JwtTokenUtil jwtTokenUtil;

	@Override
	protected void doFilterInternal(HttpServletRequest request, 
		   HttpServletResponse response, FilterChain chain)
			throws ServletException, IOException 
	{
		final String requestTokenHeader =                             request.getHeader("authorization");
		
		String username = null;
		String jwtToken = null;
		
            // JWT Token is in the form "Bearer token". 
            //Remove Bearer word and get only the Token
		if (requestTokenHeader != null &&                       requestTokenHeader.startsWith("Bearer ")) 
            {
			jwtToken = requestTokenHeader.substring(7);
			try {
				username = 
				jwtTokenUtil.getUsernameFromToken(jwtToken);

			} catch (IllegalArgumentException e) {
				System.out.println("Unable to get JWT Token");
			} catch (ExpiredJwtException e) {
				System.out.println("JWT Token has expired");
			}
		} else {
			logger.warn("JWT Token does not begin
                                with Bearer String");
		}
		// Once we get the token validate it.
		if (username != null && 
            SecurityContextHolder.getContext().getAuthentication() == null) 
		{
			UserDetails userDetails =    this.jwtUserDetailsService.loadUserByUsername(username);
		// if token is valid configure Spring Security to manually set
			// authentication
			if (jwtTokenUtil.validateToken(jwtToken, userDetails)) 
			{
				UsernamePasswordAuthenticationToken    usernamePasswordAuthenticationToken = new 		    		                        UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
				usernamePasswordAuthenticationToken
						.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
				
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
				SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
			}
		}
		chain.doFilter(request, response);
	}
}

JwtTokenUtil.java

Util class is to create and validate JWT token.

@Component
public class JwtTokenUtil implements Serializable
{
	
	public static final long JWT_TOKEN_VALIDITY = 1000 * 3600;
	
	@Value("${jwt.secret}")
	private String secret;

	// retrieve username from jwt token
	public String getUsernameFromToken(String token) {
		return getClaimFromToken(token, Claims::getSubject);
	}

	// retrieve expiration date from jwt token
	public Date getExpirationDateFromToken(String token) {
		return getClaimFromToken(token, Claims::getExpiration);
	}

	public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
		final Claims claims = getAllClaimsFromToken(token);
		return claimsResolver.apply(claims);
	}

	// for retrieveing any information from token we will need the secret key
	private Claims getAllClaimsFromToken(String token) {
		return Jwts.parser().setSigningKey(secret)
		.parseClaimsJws(token).getBody();
	}

	// check if the token has expired
	private Boolean isTokenExpired(String token) {
		final Date expiration = getExpirationDateFromToken(token);
		return expiration.before(new Date());
	}

	// generate token for user
	public String generateToken(UserDetails userDetails) {
		Map<String, Object> claims = new HashMap<>();
		String username = userDetails.getUsername();
		return doGenerateToken(claims, username);
	}

	// while creating the token -
	// 1. Define claims of the token, like Issuer, Expiration, Subject, and the ID
	// 2. Sign the JWT using the HS512 algorithm and secret key.
	// 3. According to JWS Compact
	// compaction of the JWT to a URL-safe string
	private String doGenerateToken(Map<String, Object> claims, String subject) {
		return Jwts.builder().setClaims(claims).setSubject(subject)
			.setIssuedAt(new Date(System.currentTimeMillis()))
			.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY))
			.signWith(SignatureAlgorithm.HS512, secret).compact();
	}

	// validate token
	public Boolean validateToken(String token, UserDetails userDetails) {
		final String username = getUsernameFromToken(token);
		return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
	}
}

WebSecurityConfig.java

Spring security is configured in this file that extends the websecurity configuration adapter.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
{
	@Autowired
	private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

	@Autowired
	private UserDetailsService jwtUserDetailsService;

	@Autowired
	private JwtRequestFilter jwtRequestFilter;

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		// configure AuthenticationManager so that it knows from where to load
		// user for matching credentials
		// Use BCryptPasswordEncoder
		auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**").allowedOrigins("*")
		.allowedMethods("HEAD", "GET", "PUT", "POST",
		"DELETE", "PATCH").allowedHeaders("*");
	}

	@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {
		// We don't need CSRF for this example
		httpSecurity
		.cors()
		.and()
		.csrf()
		.disable()
		.headers()
		.frameOptions()
		.deny()
		.and()
		// dont authenticate this particular request
		.authorizeRequests().antMatchers("/authenticate").permitAll().
		// all other requests need to be authenticated
		anyRequest().authenticated().and().
		// make sure we use stateless session; session won't be used to
		// store user's state.
		exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
		.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
		// Add a filter to validate the tokens with every request
		httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
	}
}

1.4 Create the following files in the controller package.

HelloWorldController.java

Simple rest API to test request, after token authentication successful, the request will come here

@RestController
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class HelloWorldController {

	@RequestMapping("/dashboard")
	public String firstPage() {
		return "success";
	}
}

JwtAuthenticationController.java

This file contains authentication rest API that receives the username and password for authentication and it returns the JWT token on successful response.

@RestController
@CrossOrigin
public class JwtAuthenticationController {
	
	@Autowired
	private AuthenticationManager authenticationManager;
	
	@Autowired
	private JwtTokenUtil jwtTokenUtil;
	
	@Autowired
	private JwtUserDetailsService userDetailsService;
	
	@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
	public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest authenticationRequest) throws Exception 
	{
		//authenticate(authenticationRequest.getUsername(), 
		authenticationRequest.getPassword());
		final UserDetails userDetails = 
		 userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
		//JwtUserDetails userDetails = new JwtUserDetails();
		//userDetails.setUsername(authenticationRequest.getUsername());
			
			
		final String token = jwtTokenUtil.generateToken(userDetails);
		return ResponseEntity.ok(new JwtResponse(token));
	}
	
	private void authenticate(String username, String password) throws Exception {
		try {
			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
		} catch (DisabledException e) {
			throw new Exception("USER_DISABLED", e);
		} catch (BadCredentialsException e) {
			throw new Exception("INVALID_CREDENTIALS", e);
		}
	}
	
}

1.5 Create following files in model package.

JwtRequest.java

It’s a pojo class that contains a username and password to get a request data in an authentication method.

public class JwtRequest implements Serializable {
	
	private String username;
	private String password;

	// need default constructor for JSON Parsing
	public JwtRequest() {

	}

	public JwtRequest(String username, String password) {
		this.setUsername(username);
		this.setPassword(password);
	}

	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
}

JwtResponse.java

Its pojo class that return jwt token string and if we need other field to send as response then need to declare a field in this file.

public class JwtResponse implements Serializable
{
	
	private final String jwttoken;

	public JwtResponse(String jwttoken) {
		this.jwttoken = jwttoken;
	}

	public String getToken() {
		return this.jwttoken;
	}
}

JwtUserDetails.java

The class which contains spring security user details fields.

@SuppressWarnings("serial")
public class JwtUserDetails implements org.springframework.security.core.userdetails.UserDetails {

	private String username;

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return null;
	}

	@Override
	public String getPassword() {
		return null;
	}
                                                                                                                                                                                                                   
	@Override
	public String getUsername() {
		return username;
	}

	@Override
	public boolean isAccountNonExpired() {
		return false;
	}

	@Override
	public boolean isAccountNonLocked() {
		return false;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return false;
	}

	@Override
	public boolean isEnabled() {
		return false;
	}

	public void setUsername(String username) {
		this.username = username;
	}

}

1.6 Create JwtUserDetailsService in service package.

JwtUserDetailsService.java

To validate username and password and return user details object.

@Service
public class JwtUserDetailsService implements UserDetailsService {
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
	{
		if ("admin".equals(username)) 
		{
			return new User("admin", "$2a$10$slYQmyNdGzTn7ZLBXBChFOC9f6kFjAqPhccnP6DxlWXx2lPk1C3G6",
					new ArrayList<>());
		} else {
			throw new UsernameNotFoundException("User not found with username: " + username);
		}
	}
}

Now we have done with server side setup and next will move to the second step.

2. Creating React JS application and accessing rest API using JWT token.

Run the below command in command prompt to generate react application.

Command : npx create-react-app demo-app

After creating application use prefered IDE to import.

Understanding the React js Project Structure

Following screenshot shows the structure of the React js project and Inside src folder we are going to create the login.js , dashboard.js and Interceptors file like below.

2.1.Login.js  

Here we have a hardcoded username and password, after successful login, we will receive JWT token as a response from a server that is saved in local storage.

import React, { Component } from "react";
import axios from "axios";

class login extends Component {
  constructor() {
    super();

    this.state = {
      username: "admin",
      password: "admin"
    };
    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }

  handleFormSubmit = event => {
    event.preventDefault();

    const endpoint = "http://localhost:8080/authenticate";

    const username = this.state.username;
    const password = this.state.password;

    const user_object = {
      username: username,
      password: password
    };

    axios.post(endpoint, user_object).then(res => {
      localStorage.setItem("authorization", res.data.token);
      return this.handleDashboard();
    });
  };

  handleDashboard() {
    axios.get("http://localhost:8080/dashboard").then(res => {
      if (res.data === "success") {
        this.props.history.push("/dashboard");
      } else {
        alert("Authentication failure");
      }
    });
  }

  render() {
    return (
      <div>
        <div class="wrapper">
          <form class="form-signin" onSubmit={this.handleFormSubmit}>
            <h2 class="form-signin-heading">Please login</h2>
            <div className="form-group">
              <input type="text"
                class="form-control"
                placeholder="User name"
                value="admin"
              />
            </div>
            <div className="form-group">
              <input type="password"
                class="form-control"
                placeholder="password"
                value="admin"
              />
            </div>
            <button class="btn btn-lg btn-primary btn-block" type="submit">
              Login
            </button>
          </form>
        </div>
      </div>
    );
  }
}
export default login;

2.2.Dashboard.js

This is the Home page of the application after logging.

import React, { Component } from "react";

class dashboard extends Component {
  handleLogout() {
    localStorage.clear();
    window.location.href = "/";
  }

  render() {
    return (
      <div>
        <h1>WELCOME TO DASHBOARD</h1>
        
        <a
          href="javascript:void(0);"
          onClick={this.handleLogout}
          className="d-b td-n pY-5 bgcH-grey-100 c-grey-700">
          <i className="ti-power-off mR-10"></i>
          <span style={{ color: "white" }}>Logout</span>
        </a>
      </div>
    );
  }
}
export default dashboard;

2.3.Interceptors.js

This is a global configuration that will intercept each request by adding an authorization header with a JWT token that is stored in local storage.

var axios = require("axios");

export const jwtToken = localStorage.getItem("authorization");

axios.interceptors.request.use(
  function(config) {
    if (jwtToken) {
      config.headers["authorization"] = "Bearer " + jwtToken;
    }
    return config;
  },
  function(err) {
    return Promise.reject(err);
  }
);

2.4.App.js

This file is an entry component for react application, the new route should be configured when a new file is added like below.

import React from "react";
import "./App.css";
import { BrowserRouter, Route } from "react-router-dom";
import interceptors from "../src/Interceptors";
import login from "./login";
import dashboard from "./dashboard";

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <BrowserRouter>
          <Route exact path="/" component={login} />
          <Route exact path="/dashboard" component={dashboard} />
        </BrowserRouter>
      </header>
    </div>
  );
}

export default App;

Note : Once all the files are added in the react application, start the spring boot application and start npm development server using the below command.

Command : npm start

Once the application has started, you can access the application using below url.

URL : http://localhost:3000

 

JWT Authentication URLs

You can send a POST request to

http://domain-name:port/authenticate with the request body containing the credentials.

{

  “username”:”admin”,

  “password”:”admin”

}

The Response contains the JWT token

{
"token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJyYW5nYSIsImV4cCI6MTU0MjQ3MjA3NCwiaWF0IoxNTQxODY3Mjc0fQ.kD6UJQyxjSPMzAhoTJRr-Z5UL-FfgsyxbdseWQvk0fLi7eVXAKhBkWfj06SwH43sY_ZWBEeLuxaE09szTboefw"
}

Since this is the demo project, the application will work only for below username and password.

After the successful login the application landed on the home page that looks similar to below image.

Conclusion

In this article, we added authentication to our React Js app. We secured our REST APIs in the server-side and our private routes at the client-side.

Kubernetes Security Practices on AWS

By | Blogs, Cloud, Cloud Assessment, Kubernetes | One Comment

Written by Praful Tamrakar Senior Cloud Engineer, Powerupcloud Technologies

Security in Cloud and Infra level

  1. Ensure the worker nodes AMI meet the CIS benchmark. 
    1. For K8s benchmark :
    1. Below is a list of tools and resources that can be used to automate the validation of an instance of Kubernetes against the CIS Kubernetes Benchmark:
  1. Verify that the Security Groups and NACL do not allow all traffic access and the rules allow access to ports and Protocol needed only for Application and ssh purposes.
  2. Make sure that you have encryption of data at rest. Amazon KMS can be used for encryption of data at rest. For Example : 
  • EBS volumes for ControlPlane nodes and worker nodes can be encrypted via KMS.
  • You can encrypt the  Logs Data either in Cloudwatch Logs or  in S3 using KMS.
  1. If Instance(s) are behind the ELB, make sure you have configured HTTPS encryption and decryption process (generally known as SSL termination) handled by an Elastic Load Balancer.
  2. Make sure the worker nodes and RDS are provisioned in Private Subnets.
  3. It’s always best practise to have a Separate Kubernetes(EKS) cluster for each Environment( Dev/UAT/Prod).
  4. Ensure to use AWS Shield/WAF to prevent DDOS attacks.

Container Level

  1. Ensure to use a minimal base image ( Eg: Alpine image to run the App)
  2. Ensure  that the docker image  registry you are using is a trusted, authorized and private registry. EG: Amazon ECR.
  3. Make sure you remove all the unnecessary files in your docker image. Eg: In tomcat server, you need to remove: 
  • $CATALINA_HOME/webapps/examples
  • $CATALINA_HOME/webapps/host-manager
  • $CATALINA_HOME/webapps/manager
  • $CATALINA_HOME/conf/Catalina/localhost/manager.xml 
  1. Ensure to disable the display of the app-server version or server information. For example, below in the Tomcat server, we can see the server information is displayed. This can be mitigated using the procedure below.

Update an empty value to server.info(server.info=””) in the file,$CATALINA_HOME/lib/org/apache/catalina/util/ServerInfo.properties

  1. Ensure not to copy or add any sensitive file/data in the Docker image, it’s always recommended to use Secrets ( K8s secrets are encrypted at rest by default onwards Kubernetes v1.13 )  You may also use another secret management tool of choice such as  AWS Secret Manager/Hashicorp Vault.
    • Eg: do not enter Database Endpoints, username, passwords in the docker file. Use K8s secrets and these secrets can be used as an Environmental variables  
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: myapp
    image: myapp
    env:
      - name: DB_USERNAME
        valueFrom:
          secretKeyRef:
            name: dbsecret
            key: username
      - name: DB_PASSWORD
        valueFrom:
          secretKeyRef:
            name: dbsecret
            key: password
      - name: DB_ENDPOINT
        valueFrom:
          secretKeyRef:
            name: dbsecret
            key: endpoint

5. Ensure to disable Bash from the container images.

6. Endorse Multi-Stage build for smaller, cleaner and secure images.

To understand how can you leverage multi-stage can be found on :

https://docs.docker.com/develop/develop-images/multistage-build/

7. Verify that the container images are scanned for vulnerability assessment before it is pushed to the registry. The AWS ECR has the feature that you can scan Repository to Scan on Push. Eg : CLAIR/AQUA/etc assessment tools can be used to scan images. These tools can be embedded in the CI/CD pipeline making sure if there is any vulnerability, the docker image push can be rejected/terminated. Find sample implementation  – https://www.powerupcloud.com/email-va-report-of-docker-images-in-ecr/

K8s level

  1. Make sure to use or upgrade Kubernetes to the latest stable version.
  2. It’s recommended not to use default namespace. Instead, create a namespace for each application, i.e separate Namespaces for separate sensitive workloads.
  3. Make sure to enable Role-Based Access Control (RBAC) for Clients( Service Accounts / Users) for restricted privileges.

RBAC Elements:

  • Subjects: The set of users and processes that want to access the Kubernetes API.
  • Resources: The set of Kubernetes API Objects available in the cluster. Examples include Pods, Deployments, Services, Nodes, and PersistentVolumes, among others.
  • Verbs: The set of operations that can be executed to the resources above. Different verbs are available (examples: get, watch, create, delete, etc.), but ultimately all of them are Create, Read, Update or Delete (CRUD) operations.

Let’s see  RBAC meant for seeing Kubernetes as a production-ready platform.

  • Have multiple users with different properties, establishing a proper authentication mechanism.
  • Have full control over which operations each user or group of users can execute.
  • Have full control over which operations each process inside a pod can execute.
  • Limit the visibility of certain resources of namespaces.

4. Make sure to standardize the naming and labeling Convention of the Pod, Deployment, and service. This will ease the operational burden for security management ( Pod Network Policy ).

5. Ensure to use Kubernetes network policy which will restrict the  Pods communication, i.e how groups of pods are allowed to communicate with each other and other network endpoints. Please find how to implement the network policy in Amazon EKS https://blog.powerupcloud.com/restricting-k8s-services-access-on-amazon-eks-part-ix-7d75c97c9f3e

6. AWS Single Sign-On (SSO), AWS Managed Microsoft Active Directory Service, and the AWS IAM authenticator can be used to control access to your Amazon EKS cluster running on the AWS cloud.

7. Corroborate to use Pod Security Context.

  • Ensure to disable root access. the docker image should be accessible from a non-root user
  • Make sure to configure read-only root file system
  • Security-Enhanced Linux (SELinux): You can assign SELinuxOptions objects using the seLinuxOptions field. Note that the SELinux module needs to be loaded on the underlying Linux nodes for these policies to take effect.
  • Make sure  Linux capabilities and/or add non-default Linux capabilities are used if it’s required.
  • Make sure not to run pods/containers as privileged unless you will require access to all devices on the host. Permission to access an object, like a file, is based on user ID (UID) and group ID (GID).

Please Find the  Snippet for Pod Security Context  :

...
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
    seLinuxOptions:
    level: "s0:c123,c456"
    capabilities:
      drop:
        - NET_RAW
        - CHOWN
      add: ["NET_ADMIN", "SYS_TIME"]
...

Note : Pod Security content can be used in pod as well as container level.

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-2
spec:
  #Pod level
  securityContext:
    runAsUser: 1000
  containers:
  - name: sec-ctx-demo-2
    image: gcr.io/google-samples/node-hello:1.0
   #container level
    securityContext:
      runAsUser: 2000
      allowPrivilegeEscalation: false

8. Make sure to embed these Kubernetes Admission Controllers in all possible ways.

  • AlwaysPullImages – modifies every new Pod to force the image pull policy to Always. This is useful in a multitenant cluster so that users can be assured that their private images can only be used by those who have the credentials to pull them.
  • DenyEscalatingExec – will deny exec and attach commands to pods that run with escalated privileges that allow host access. This includes pods that run as privileged, have access to the host IPC namespace or have access to the host PID namespace.
  • ResourceQuota – will observe the incoming request and ensure that it does not violate any of the constraints enumerated in the ResourceQuota object in a Namespace.
  • LimitRanger- will observe the incoming request and ensure that it does not violate any of the constraints enumerated in the LimitRange object in a Namespace. Eg: CPU and Memory

10. Ensure to scan Manifest files (yaml/json) for which any credentials are passed in objects ( deployment, charts )  Palo Alto Prisma / Alcide Kubernetes Advisor.

11. Ensure to use TLS authentication for Tiller when Helm is being used.

12. It’s always recommended not to use a default Service account

  • The default service account has a very wide range of permissions in the cluster and should, therefore be disabled.

13. Do not create a Service Account or a User which has full cluster-admin privileges unless necessary,  Always follow Least Privilege rule.

14. Make sure to disable anonymous access and send Unauthorized responses to unauthenticated requests. Verify the following Kubernetes security settings when configuring kubelet parameters:

  • anonymous-auth is set to false to disable anonymous access (it will send 401 Unauthorized responses to unauthenticated requests).
  • kubelet has a `–client-ca-file flag, providing a CA bundle to verify client certificates.
  • –authorization-mode is not set to AlwaysAllow, as the more secure Webhook mode will delegate authorization decisions to the Kubernetes API server.
  • –read-only-port is set to 0 to avoid unauthorized connections to the read-only endpoint (optional).

15. Ensure to put restricted access to etcd from only the API server and nodes that need that access. This can be restricted in the Security Group attached to ControlPlane.

K8s API call level

  1. Ensure that all the communication from the client(Pod/EndUser) to the K8s(API SERVER) should be TLS encrypted
    1. May experience throttle if huge API calls happen
  2. Corroborate that all the communication from k8s API server to ETCD/Kube Control Manager/Kubelet/worker node/Kube-proxy/Kube Scheduler  should be TLS encrypted
  3. Enable Control Plane API to call logging and Auditing. ( EG:  EKS Control Plane Logging)
  4. If you are using Managed Services for K8s such as Amazon  EKS, GKE, Azure Kubernetes Service (AKS), these all things are taken care

EKS Security Considerations

  • EKS does not support Kubernetes Network Policies or any other way to create firewall rules for Kubernetes deployment workloads apart from Security Groups on the Worker node, since it uses VPC CNI plugin by default, which does not support network policy. Fortunately, this has a simple fix. The Calico CNI can be deployed in EKS to run alongside the VPC CNI, providing Kubernetes Network Policies support.
  • Ensure to Protect EC2 Instance Role Credentials and Manage AWS IAM Permissions for Pods. These can be configured by using below tools:
  • By using the IAM roles for the service accounts feature, we no longer need to provide extended permissions to the worker node’s IAM role so that pods on that node can call AWS APIs. We can scope IAM permissions to a service account, and only pods that use that service account have access to those permissions. This feature also eliminates the need for third-party solutions such as kiam or kube2iam.

https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html

Security Monitoring of K8s

Sysdig Falco is an open-source, container security monitor designed to detect anomalous activity in your containers. Sysdig Falco taps into your host’s (or Node’s in the case Kubernetes) system calls to generate an event stream of all system activity. Falco’s rules engine then allows you to create rules based on this event stream, allowing you to alert on system events that seem abnormal. Since containers should have a very limited scope in what they run, you can easily create rules to alert on abnormal behavior inside a container.

Ref: https://sysdig.com/opensource/falco/

The Alcide Advisor is a Continuous Kubernetes and Istio hygiene checks tool that provides a single-pane view for all your K8s-related issues, including audits, compliance, topology, networks, policies, and threats. This ensures that you get a better understanding and control of distributed and complex Kubernetes projects with a continuous and dynamic analysis. A partial list of the checks we run includes:

  • Kubernetes vulnerability scanning
  • Hunting misplaced secrets, or excessive secret access
  • Workload hardening from Pod Security to network policies
  • Istio security configuration and best practices
  • Ingress controllers for security best practices.
  • Kubernetes API server access privileges.
  • Kubernetes operators security best practices.

Ref :https://aws.amazon.com/blogs/apn/driving-continuous-security-and-configuration-checks-for-amazon-eks-with-alcide-advisor/

Automate and Manage AWS KMS from Centralized AWS Account

By | AWS, Blogs, Cloud, Cloud Assessment | No Comments

Written by Priyanka Sharma, DevOps Architect, Powerupcloud Technologies

As we have discussed in our previous blog that we use the AWS Landing Zone concept for many of our customers which consists of separate AWS accounts so they can meet the different needs of their organization. One of the accounts is the Security account where the security-related components reside. KMS Keys are one of the security-related key components that helps in the encryption of data. 

A Customer Master Key (CMK) is a logical representation of a master key which includes the following details:

  • metadata, such as the key ID, creation date, description
  • key state
  • key material used to encrypt and decrypt data.

There are three types of AWS KMS:

  • Customer Managed CMK: CMKs that you create, own, and manage. You have full control over these CMKs.
  • AWS Managed CMK: CMKs that are created, managed, and used on your behalf by an AWS service that is integrated with AWS KMS. Some AWS services support only an AWS managed CMK.
  • AWS Owned CMK:  CMKs that an AWS service owns and manages for use in multiple AWS accounts. You do not need to create or manage the AWS owned CMKs.

This blog covers the automation of Customer Managed CMKs i.e. how we can use the Cloudformation templates to create the Customer Managed CMKs. It also discusses the strategy that we follow for our enterprise customers for enabling encryption in cross accounts. 

KMS Encryption Strategy

We are covering the KMS strategy that we follow for most of our customers.

In each of the Accounts, create a set of KMS Keys for the encryption of data. For example,

  • UAT/EC2
    • For enabling the default EC2 encryption, go to Ec2 dashboard settings in the right-hand side as shown in the below screenshot:

Select “Always encrypt the EBS volumes” and Change the default key. Paste the ARN of the UAT/EC2 KMS Key ARN.

  • UAT/S3
    • Copy the ARN of UAT/S3 KMS Key ARN.
    • Go to Bucket Properties and Enable Default Encryption with Custom AWS-KMS. Provide the KMS ARN from the security account.
  • UAT/RDS
    • This Key can be used while provisioning the RDS DB instance.
    • Ensure to provide the Key ARN if using via cross-account
  • UAT/OTHERS

Automated KMS Keys Creation

Below Cloudformation template can be used to create a set of KMS Keys as follows:

https://github.com/powerupcloud/automate-kms-keys-creation/blob/master/kms-cf-template.json

Ensure to replace the SECURITY_ACCOUNT_ID variable with the 12-digit AWS security account ID where KMS keys will be created.

The CF Template does the following:

  • Creates the below KMS Keys in the Target Account:
    • PROD/EC2
      • It is used to encrypt the EBS Volumes.
    • PROD/S3
      • Used to encrypt the S3 buckets.
    • PROD/RDS
      • Used to encrypt the RDS data.
    • PROD/OTHERS
      • It can be used to encrypt the AWS resources other than EC2, S3, and RDS. For example, if EFS requires to be created in the production account, PROD/OTHERS KMS key can be used for the encryption of EFS.
  • In our case, we are using the Landing Zone concept, so the “OrganizationAccountAccessRole” IAM Role used for Switch Role access from Master account is one of the Key Administrator.
  • Also, We have enabled the Single sign-on in our account, the IAM Role created by SSO “AWSReservedSSO_AdministratorAccess_3687e92578266b74″ has also the Key Administrator access.

The Key administrators can be changed as required in the Key Policy.

The “ExternalAccountID” in the Cloudformation parameters is used to enable the cross-account access via KMS Key policy.

Hope you found it useful.

Transfer Data from Mysql to BigQuery using Data Fusion Pipeline

By | Blogs, Cloud Assessment, data, Data pipeline | One Comment

Written by Anjali Sharma, Software Engineer at Powerupcloud Technologies

What is Cloud Data Fusion Pipeline? –

Cloud Data fusion is an enterprise data integration service provided by Google for quickly building and managing pipelines. A fully managed, cloud-native platform where a source(MySQL) and sink(bigquery) can be connected easily without using any code.

Since it’s a code-free environment anyone can use it easily without having any hindrances of technical skills or coding knowledge.

Cloud Data Fusion is built on the open-source project CDAP, and this open core ensures data pipeline portability for users. CDAP’s broad integration with on-premises and public cloud platforms gives Cloud Data Fusion users the ability to break down silos and deliver insights that were previously inaccessible.

How it does look on Cloud Data Fusion Platform

Why Cloud Data Fusion?

Now the question arises, why do we use cloud data fusion as we have other options to make a connection from MySQL DB to bigquery for ETL/ELT.

Data fusion pipelines provide fully managed, virtual interface, easy to use, fully scalable, fully distributed platform that enables you to connect to many different data sources easily.

Data fusion pipelines have the flexibility to have all the pipelines as code and enable you to use rest API calls to create and trigger pipelines. Hence cloud data fusion is a complete package to develop data pipelines easily and efficiently.

How do we create the data pipeline? –

Creating data fusion pipeline is quite easy on the Google cloud platform, we can get it done by following a few steps-

Step1- Go to GCP console find Cloud data fusion click on ‘Create Instance’.

Step2- Fill the instance name and region name and click on create.

Step3- It will take 10-15 minutes to create an instance, now go to view instance and click on redirect URL.

Step4-  Now you are inside cloud data fusion instance, click on HUB and choose a pipeline(import data from MySQL).

Step5- Along with pipelines in HUB you are getting several options. Choose import data from MySQL. Now we’re going to install Driver.

Step6-  Install Google cloud JDBC driver which will make a connection to let MySQL database communicate bigquery. We can find the driver from here itself but make sure the driver is of the latest version.

Step7-  Now go to Navigation Bar and click on the control center.

Step8-  Go to green encircled plus symbol and upload the latest version of JDBC driver.

Step9- Give a name to the driver and a suitable class name which is invalid format com.example.myclass and click on finish.

Step10- Now again go to HUB, click on import data from MySQL pipeline and click on create. Give a name to the pipeline and finish. Now you are able to customize your pipeline.

Here in the cloud data fusion studio we can change source and sink accordingly as here we need to connect Database(source) to Bigquery(sink).

Step11- Go to database properties and fill the plugin name and types. After filling the details Browse database and click on Add connection.

Step12- Here you will find installed Mysql driver click on it and put connection name, host, port, database name, id, password.

Step13- Test the connection and add it.

Step14- Now you are able to import your query. Deploy the Pipeline.

Step15- You have deployed your data fusion pipeline successfully.

Conclusion

Cloud Data Fusion takes care of most of ETL/ELT works for you. And since it’s part of Google Cloud, you can take advantage of built-in security benefits when using Cloud Data Fusion rather than self-managed CDAP servers:

  • Cloud-native security control with Cloud IAM—Identity management and authentication efforts are taken care of by Cloud Identity.
  • Full observability with Stackdriver Logging and Monitoring—Logs include pipeline logs and audit logs
  • Reduced exposure to the public internet with private networking.

Cloud Data Fusion offers both preconfigured transformations from an OSS library as well as the ability to create an internal library of custom connections and transformations that can be validated, shared, and reused across an organization. It lays the foundation for collaborative data engineering and improves productivity. That means less waiting for data engineers and, importantly, less sweating about code quality.

Running Amazon EKS behind Customer HTTP Proxy without NAT

By | Blogs, Cloud, Cloud Assessment | One Comment

Written by Praful Tamrakar and Manoj S Rao, Senior Cloud Engineer, Powerupcloud Technologies

Most of the enterprise customers would use the Proxy for the indirect network connections to other network services.

One of our customers has the following network configurations in AWS:

  • No AWS NAT gateway and Internet Gateway  for outbound traffic
  • All the traffic to the Internet must go via Proxy to reduce surface attacks and all such traffic will be monitored pro-actively.
  • All URLs outside the VPC must be whitelisted

The DNS and proxy resolution Diagram

Problem Statement:

With the above networking configurations, we had a requirement to have an EKS Cluster in private subnets. We faced multiple challenges (as mentioned below) with the EKS connectivity.

To join the worker nodes to an EKS cluster, we require to execute a bootstrap command through the user-data script in the EC2 server. With our networking configurations, the kubelet was not able to start after executing the bootstrap command and we were facing connection timed out  issues in the below two scenarios:

  1. When the kubelet service was trying to pull the pod-infra-container image from the docker API call.
  2. When kubelet service was trying to connect to EC2 and ECR API call

With the below solution we were able to resolve both the issues and run EKS behind the proxy successfully.

In this article, we are elaborating on how we can achieve and automate the configuration of an HTTP proxy for Amazon Elastic Kubernetes Service (Amazon EKS) worker nodes with the help of user data.

Assumptions and requisites:

  1. This solution can be used for either Terraform or Amazon Cloudformation which will help you to create an EKS cluster worker-node initial setup or upgrading the worker node.

The cloud formation script can be found on ->

https://github.com/powerupcloud/kubernetes-spot-webinar/tree/master/provision-eks-worker-nodes

The terraform Script can be found on ->

https://learn.hashicorp.com/terraform/aws/eks-intro

  1. You must edit the user-data on both the above method with the solution mentioned below.
  2. IF the EKS cluster API Endpoint setup is a Private subnet and does not have NAT Gateway,  Please setup VPC endpoint for Amazon EC2 and Amazon ECR. ( please ensure the EC2 and ECR endpoint Security Groups must be same as the worker node Security Group)

Resolution

1.    Let’s find out the CIDR Block of the cluster :

kubectl get service kubernetes -o jsonpath='{.spec.clusterIP}'; echo

This will return either 10.100.0.1, or 172.20.0.1, which means that your cluster IP CIDR block is either 10.100.0.0/16 or 172.20.0.0/16.

2.    Let’s create a ConfigMap file named proxy-env-vars-config.yaml.

If the output from the command in step 1 has an IP from the range 172.20.x.x, then structure your ConfigMap file will be:

apiVersion: v1
kind: ConfigMap
metadata:
name: proxy-environment-variables
namespace: kube-system
data:
HTTPS_PROXY:http://customer.proxy.host:proxy_port
HTTP_PROXY: http://customer.proxy.host:proxy_port
NO_PROXY: 172.20.0.0/16,localhost,127.0.0.1,VPC_CIDR_RANGE,169.254.169.254,.internal,.s3.amazonaws.com,.s3.<aws-region-code>.amazonaws.com

If the output from the command in step 1 has an IP from the range 10.100.x.x, then structure your ConfigMap file as follows:

apiVersion: v1
kind: ConfigMap
metadata:
name: proxy-environment-variables
namespace: kube-system
data:
HTTPS_PROXY:http://customer.proxy.host:proxy_port
HTTP_PROXY: http://customer.proxy.host:proxy_port
NO_PROXY: 10.100.0.0/16,localhost,127.0.0.1,VPC_CIDR_RANGE,169.254.169.254,.internal,.s3.amazonaws.com,.s3.<aws-region-code>.amazonaws.com

3. Now we will create a  ConfigMap :

kubectl apply -f /path/to/yaml/proxy-env-vars-config.yaml

Consider the following:

  • If you use a VPC endpoint, add a public endpoint subdomain to NO_PROXY (for example, with an Amazon Simple Storage Service (Amazon S3) endpoint in the region you run your EK cluster.).
  • You don’t need a proxy configuration to communicate, because the kube-dns pod communicates directly with the Kubernetes service.
  • Verify that the NO_PROXY variable in the proxy-environment-variables ConfigMap (used by the kube-proxy and aws-node pods) includes the Kubernetes cluster IP address space.

4.   Now we will come to Bootstrapping the worker nodes to configure the Docker daemon and kubelet by injecting user data into your worker nodes.

We must update or create yum, Docker, and kubelet configuration files before starting the Docker daemon and kubelet.

Let’s take user data injected into worker nodes using an AWS CloudFormation template that’s launched from the AWS Management Console, see Launching Amazon EKS Worker Nodes.

#Set the proxy hostname and port
PROXY="http://customer.proxy.host:proxy_port"
VPC_CIDR=VPC_CIDR_RANGE

#Create the docker systemd directory
mkdir -p /etc/systemd/system/docker.service.d

#Configure yum to use the proxy
cat << EOF >> /etc/yum.conf
proxy=http://$PROXY
EOF

#Set the proxy for future processes, and use as an include file
cat << EOF >> /etc/environment
http_proxy=$PROXY
https_proxy=$PROXY
HTTP_PROXY=$PROXY
HTTPS_PROXY=$PROXY
no_proxy=$VPC_CIDR,localhost,127.0.0.1,169.254.169.254,.internal,.<aws-region-code>.eks.amazonaws.com
NO_PROXY=$VPC_CIDR,localhost,127.0.0.1,169.254.169.254,.internal,.<aws-region-code>.eks.amazonaws.com
EOF

#Configure docker with the proxy
tee <<EOF /etc/systemd/system/docker.service.d/proxy.conf >/dev/null
[Service]
EnvironmentFile=/etc/environment
EOF


#Configure the kubelet with the proxy
tee <<EOF /etc/systemd/system/kubelet.service.d/proxy.conf >/dev/null
[Service]
EnvironmentFile=/etc/environment
EOF

#!/bin/bash
set -o xtrace

#Set the proxy variables before running the bootstrap.sh script
set -a
source /etc/environment

/etc/eks/bootstrap.sh ${ClusterName} ${BootstrapArguments}
/opt/aws/bin/cfn-signal
    --exit-code $? \
    --stack  ${AWS::StackName} \
    --resource NodeGroup  \
    --region ${AWS::Region}

5. To update the AWS-node and Kube-proxy pods, run the following commands:

kubectl patch -n kube-system -p '{ "spec": {"template": { "spec": { "containers": [ { "name": "aws-node", "envFrom": [ { "configMapRef": {"name": "proxy-environment-variables"} } ] } ] } } } }' daemonset aws-node

kubectl patch -n kube-system -p '{ "spec": {"template":{ "spec": { "containers": [ { "name": "kube-proxy", "envFrom": [ { "configMapRef": {"name": "proxy-environment-variables"} } ] } ] } } } }' daemonset kube-proxy

6. If you change the ConfigMap, apply the updates, and then set the ConfigMap in the pods again to initiate an update as follows:

kubectl set env daemonset/kube-proxy --namespace=kube-system --from=configmap/proxy-environment-variables --containers='*'

kubectl set env daemonset/aws-node --namespace=kube-system --from=configmap/proxy-environment-variables --containers='*'

Note: You must update all YAML modifications to the Kubernetes objects kube-dns or AWS-node when these objects are upgraded. To update a ConfigMap to a default value :

With EKSCTL:

eksctl utils update-kube-proxy

WARNINGS :

If the proxy loses connectivity to the API server, then the proxy becomes a single point of failure and your cluster’s behavior can become unpredictable. For this reason, it’s best practice to run your proxy behind a service discovery namespace or load balancer, and then scale as needed.

And that’s all..!! Hope you found it useful. Keep following our Kubernetes series for more interesting articles.

References:

Creating and Updating a Secured AWS Account using Account Vending Machine

By | Blogs, Cloud, Cloud Assessment | No Comments

Written by Priyanka Sharma, DevOps Architect, Powerupcloud Technologies

Many of the customers use the AWS Landing Zone concept which consists of separate AWS accounts so they can meet the different needs of their organization. For one of our customers, we have the below accounts setup using Landing Zone:

  • Master Account: The Main Account where the AWS Organizations are created for the separate accounts. This is the login point for all the organizations.
  • SharedServices Account: The common practices are enabled in this account. All the tools shared across multiple accounts reside here. For example, Common EC2 servers for DevOps practices such as Jenkins, SonarQube, Nexus, etc.
  • Logging Account: This account is majorly used for gathering the logs across all the accounts. Security Account: This account acts as a master account for GuardDuty and all the findings across all the organizations are fetched here.
  • Dev/UAT/Prod Accounts: These accounts are for applications..

Although multiple organizations have simplified the operational issues and provide isolation based on the functionality, it takes manual efforts to configure the baseline security practices. To save time and effort in creating the new account, we use “Account Vending Machine”. The Account Vending Machine (AVM) is an AWS Landing Zone key component. The AVM is provided as an AWS Service Catalog product, which allows customers to create new AWS accounts pre-configured with an account security baseline. For an overview, the AVM uses the below AWS Services:

  • AWS Service Catalog
  • AWS Lambda
  • AWS Organizations
  • S3 Bucket

In this blog, we are discussing how we can create, update and delete (CUD) an AWS account using AVM. The new account will be created with the following Baseline services preconfigured in it.

  • AWS Cloudtrail: It can log, continuously monitor, and retain account activity related to actions across your AWS infrastructure
  • AWS Config: Enables you to assess, audit, and evaluate the configurations of your AWS resources.
  • AWS Guardduty: Threat detection service that continuously monitors for malicious activity and unauthorized behavior to protect your AWS accounts and workloads.
  • AWS Config Rule: Managed rules for the ideal configuration settings.

The Cloudformation templates and Lambda Script are uploaded to the below Github Repo.

https://github.com/powerupcloud/account-vending-machine

Copy the CF templates in an S3 bucket and provide the S3 path while creating the Cloudformation stack.

Prerequisites

The CF templates and the python scripts are stored in a S3 bucket of the Master account. Below are the templates/scripts which are used in the AVM workflow:

  • Cloudformation Templates:
    • 01AccountCreationLambdaSetup-cfn.yaml

To start off the AVM Infrastructure, Cloudformation stack to be created with this template which creates the below two resources:

  • Service Catalog AVM Product
    • Lambda Function
    • 02Accountbuilder.yml

Creates a custom resource that triggers the Lambda Function with the required parameters. This template is required while launching the Service Catalog AVM Product.

  • 03Accountbaselinetemplate.yml

The Lambda function will create a Cloudformation stack with this baseline template in the newly created target account. It creates the predefined service catalog products such as:

  • Cloudtrail Service Catalog Product
    • Config Service Catalog Product
    • Guardduty Service Catalog Product
  • Lambda Function

AccountCreationLambda.py: The script is required to create AWS organization in the Master account and assume the IAM Role to create Service Catalog product in the target account.

AVM Infrastructure Setup in the Master Account

Create a CF stack using the “01AccountCreationLambdaSetup-cfn.yaml” template in Master Account.

Provide the following parameters on the next page:

  • AccountAdministrator: The ARN of IAM User/Group/Role which will be performing the account creation through Service Catalog.
  • SourceBucket: Either keep the default value or provide the existing S3 Bucket Name in the Master account where the CF templates are uploaded.
  • SourceTemplate: Name of the account builder template i.e. 02accountbuilder.yml.

Create the Stack. Save the Lambda ARN from the outputs.

Use the same IAM ARN as provided in the CF parameters to log into the account and switch to Service Catalog Products.

Creating a New Account

Launch AVM Product to create a new account with the security baseline.

Give a relevant name for the product to be provisioned.

Provide the following parameters:

  • MasterLambdaArn: Arn of the Lambda function which was saved from the CF Outputs.
  • account email: Email address to be associated with the new Organization.
  • OrganizationalUnitName: Keep default for placing the organization at the root level.
  • AccountName: Proper Name for the New organization account.
  • StackRegion: Region where the CF stack will be created in the target account.
  • SourceBucket: This is the S3 bucket where you have kept your Baseline CF template. In our case, we have created a new S3 bucket in the same master account with the baseline template stored in it.
  • BaselineTemplate: Enter the Baseline CF template name which exists in the SourceBucket i.e. 03accountbaseline.yml.

Click Next, Review and Launch the Product.

The AVM Product executes the following actions in the new target account:

  • Triggers the Lambda Function which uses Organization APIs to create the new account based on the user inputs provided.
  • Assumes the OrganizationAccountAccessRole in the new account and executes the below actions:
    • Creates an IAM user service-catalog-user with the default password service-catalog-2019. The password will be asked to change at the first login.
    • Creates a IAM group ServiceCatalogUserGroup with the least privilege permissions to access AWS Service Catalog. Adds the service-catalog-user to the group.
    • Creates CF stack with the Accountbaseline.yml template which creates the below Service Catalog Products.
      • Enable-Cloudtrail
      • Enable-Config
      • Enable-Guardduty
    • Deleting the default VPCs in all AWS Regions.
    • Adds the IAM user as principal to the Service Catalog portfolio. If you login with any other IAM User/Group/Role, add the respective ARN as the principal in the Baseline Portfolio in the target account as shown below.

Launch Baseline Service Catalog Products in the Newly Created Account

Once the AVM product is launched, Go to Service Catalog Products in the target account.

When launching each product, Service Catalog provisions the Cloudformation Stack in the backend.

For Enabling Cloudtrail in the new account, Provide the below parameters:

  • S3BucketNameCloudtrail: Since we have implemented the Landing zone concept, we have enabled the Cloudtrail logs in the centralized Logging account. Ensure the existing S3 bucket in the logging account is allowed for Cross Account Cloudtrail Logs.
  • CloudTrailName: Name of the Trail.
  • S3KeyPrefixCloudtrail: Prefix in the S3 Bucket for the new account.
  • TrailLogGroupRoleName: The CF stack creates the IAM Role which pushes the trail logs to Cloudwatch as well.
  • TrailLogGroupName: Cloudwatch Log Group Name.

Similarly, to enable Config from the Service Catalog Product, provide the following parameters:

  • AwsConfigRole: Name of the Config Service Role. The IAM Role will be created by the CF stack.
  • S3BucketNameConfig: Centralized S3 bucket name for the Config Logs. We have provided the centralized bucket which exists in the Logging Account.
  • S3KeyPrefixConfig: Prefix in the S3 bucket.

For the GuardDuty, it asks for a single parameter GuarddutyMasterID which is the AccountID of the security Account which acts as a master for the Guardduty since all the findings will be pushed to the security account.

And this is how we can achieve the security practices by default with the account creation itself.

Updating an existing account

Till now we have covered the one-time setup of the baseline settings. What if you want to configure more services as the baseline settings in the existing AWS organization launched through AVM? By default, the Lambda script provided by AWS doesn’t support the Update feature of the Baseline Template. We have modified the python script and uploaded it here. Update the Lambda script in the Master account with the modified script.

A valid use case can be, let’s say, after enabling Cloudtrail, Config, and Guardduty, now you also want to enable SecurityHub through the Baseline Setup. Below steps should be followed for the update feature to work:

  • Ensure the Lambda function has the update functionality as specified in the script.
  • Update the AccountBaseline template and add the Service Catalog Product for SecurityHub in it. Ensure not to delete the existing resources. Upload the updated Baseline template, e.g AccountBaseline02.yml in the S3 bucket.
  • Go to the Provisioned Products List in the Service Catalog in the Master account.
  • Click Update provisioned product and provide the updated Baseline template name in the BaselineTemplate parameter.

Click Next and update the product. It triggers the Lambda Script and updates the existing Cloudformation Stack in the Target account to add one more Service Catalog product.

Deleting an account

The deletion of an account includes manual efforts. To leave organisation, the account must be updated with valid billing information. Ensure you have a valid Email address for the account.

Steps to follow for account deletion:

  • Switch to the account which you want to delete using the AccountID and Role OrganizationAccountAccessRole.
  • Update the Billing information.
  • Switch to the AWS Organizations. Click on “Leave organisation”.

Hope you found it useful.

References:

Azure Arc: Onboarding GCP machine to Azure

By | Azure, Blogs, Cloud, Cloud Assessment, GCP | No Comments

Written by Madan Mohan K, Associate Cloud Architect

“#Multicloud and #Hybrid cloud are not things, they are situations you find yourself in when trying to solve business problems”

In the recent past, the most organization started clinging to hybrid and multi-cloud approach. Many enterprises still face a sprawl of resources spread across multiple datacentres, clouds, and edge locations. Enterprise customers keep looking for a cloud-native control plane to inventory, organize, and enforce policies for their IT resources wherever they are, from a central place.

Azure Arc:

Azure Arc extends the Azure Resource Manager capabilities to Linux and Windows servers, and Kubernetes clusters on any infrastructure across on-premises, multi-cloud, and the edge. Organizations can use Azure Arc to run Azure data services anywhere, which includes always up-to-date data capabilities, deployment in seconds, and dynamic scalability on any infrastructure. We will have a close look at Azure Arc for Servers is currently in preview.

Azure Arc for Servers:

Using Azure Arc for servers, managing machines that are hosted outside of Azure (on-premise & other cloud providers). When these types of machines are connected to Azure using Azure Arc for servers, they become Connected Machines, and they will be treated as native resources in Azure. Each Connected machine will get a Resource ID during registration in Azure and it will be managed as part of a Resource group inside an Azure subscription. This will enable the ability to benefit from Azure features and capabilities, such as Azure Policies, and tagging.

For each machine that you want to connect to Azure, an agent package needs to be installed. Based on how recently the agent has checked in, the machine will have a status of Connected or Disconnected. If a machine has not checked-in within the past 5 minutes, it will show as Disconnected until connectivity is restored. This check-in is called a heartbeat. The Azure Resource Manager service limits are also applicable to Azure Arc for server, which means that there is a limit of 800 servers per resource group.

Supported Operating Systems:

The following versions of the Windows and Linux operating system are officially supported for the Azure Connected Machine agent:

  • Windows Server 2012 R2 and higher
  • Ubuntu 16.04 and 18.04

Networking Requirements on Remote Firewall:

The Connected Machine agent for Linux and Windows communicates outbound securely to Azure Arc over TCP port 443. During installation and runtime, the agent requires connectivity to Azure Arc service endpoints. If outbound connectivity is blocked by the firewall, make sure that the following URLs and Service Tags are not blocked:

Service Tags:

  • AzureActiveDirectory
  • AzureTrafficManager

URLs Required:

Domain Environment Azure Service Endpoints
management.azure.com Azure Resource Manager
login.windows.net Azure Active Directory
dc.services.visualstudio.com Application Insights
agentserviceapi.azure-automation.net Guest Configuration
*-agentservice-prod-1.azure-automation.net Guest Configuration
*.his.hybridcompute.azure-automation.net Hybrid Identity Service

Register Azure resource providers:

Azure Arc for servers depends on the following Azure resource providers in your subscription in order to use this service:

  • Microsoft.HybridCompute
  • Microsoft.GuestConfiguration

First, we need to register the required resource providers in Azure. Therefore, take the following steps:

Navigate to the Azure portal at https://portal.azure.com/

Log in with administrator credentials

Registration can be done either using Azure Portal or Powershell

Using Azure Portal:

https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#azure-portal

Using Azure Powershell:

Register-AzResourceProvider -ProviderNamespace Microsoft.HybridCompute

Register-AzResourceProvider -ProviderNamespace Microsoft.GuestConfiguration

In this case, we will be using Powershell to register the resource providers

Note: The resource providers are only registered in specific locations.

Connect the on-premise/cloud machine to Azure Arc for Servers:

There are two different ways to connect on-premises machines to Azure Arc.

  • Download a script and run it manually on the server.
  • Using PowerShell for adding multiple machines using a Service Principal.

When adding the single server, the best approach is to use the download script and run manually method. To connect the machine to Azure, we need to generate the agent install script in the Azure portal. This script is going to download the Azure Connected Machine Agent (AzCMAgent) installation package, install it on the on-premises machine and register the machine in Azure Arc.

Generate the agent install script using the Azure portal:

To generate the agent, install script, take the following steps:

Navigate to the Azure portal and type Azure Arc

Use https://aka.ms/hybridmachineportal instead of Azure Portal

Click on +Add.

Select Add machines using an interactive script:

Keep the defaults in Basic Pane and click on Review and generate the script.

Connect the GCP machine to Azure Arc:

GCP Instance:

To connect the GCP machine to Azure Arc, we first need to install the agent on the GCP machine. Therefore, take the following steps

Open Windows PowerShell ISE as an administrator. Paste the script, that is generated in the previous step in PowerShell, in the window and execute it.

A registration code is received during the execution of the script

Navigate to  https://microsoft.com/devicelogin Paste in the code from PowerShell and click Next

A confirmation message is displayed stating that the device is registered in Azure Arc

Validation in Azure Portal:

Now when navigating to the Azure Arc in Azure Portal we can see the GCP VM is onboarded and the status shows connected.

Managing the machine in Azure Arc:

To manage the machine from Azure, click on the machine in the overview blade

In the overview blade, it offers to add tags to the machine. Furthermore, it offers to Manage access and apply policies to the machine.

Inference:

Azure Arc acts as a centralized cloud-native control plane to inventory, organize, and enforce policies for IT resources wherever they are. With an introduction to Azure Arc, an organization can enjoy the full benefits of managing its hybrid environment and it also offers the ability to innovate using cloud technologies.